new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Expo · Router · all subjects

router-settings

99 notes in this subject, read out of this brain and free to use. This is page 1 of 2.

Example: initialRouteName with multiple route groups

Code example showing how to use unstable_settings with array syntax route groups: ```tsx export const unstable_settings = { // Used for `(foo)` initialRouteName: 'first', // Used for `(bar)` bar: { initialRouteName: 'second', }, }; ``` This configures different initial routes for different grouped layouts.

Example: Disable initialRouteName override with initial={false}

Code examples showing how to prevent initialRouteName from overriding the navigation target: ```js // Using Link component <Link href="/route" initial={false} />; // Using imperative navigation router.push('/route', { overrideInitialScreen: false }); ``` Both approaches prevent the layout's initialRouteName from changing which route is shown when navigating to a new _layout.

initialRouteName only affects deep linking, not navigation

The initialRouteName setting is only used when deep-linking to a route. During normal app navigation, the route you navigate to will be the initial route shown, not the initialRouteName. This behavior can be disabled using the initial={false} prop on the Link component or by passing overrideInitialScreen: false to imperative APIs like router.push().

unstable_settings initialRouteName for back button on deep links

The initialRouteName property in unstable_settings sets the default screen of a stack layout and ensures a back button is available when deep linking to any route. The value should match a valid filename without the extension. For example, setting initialRouteName to 'index' means deep linking directly to '/other' or reloading the page will continue to show the back arrow.

unstable_settings does not work with async routes

The unstable_settings feature currently does not work with async routes in development-only scenarios. This is why the feature is designated as unstable. Users should be aware of this limitation when using async routes.

Example: unstable_settings initialRouteName in layout

Code example showing how to configure initialRouteName in a layout file: ```tsx src/app/_layout.tsx import { Stack } from 'expo-router'; export const unstable_settings = { // Ensure any route can link back to `/` initialRouteName: 'index', }; export default function Layout() { return <Stack />; } ``` This configuration ensures that deep linking to any route preserves the back button by treating 'index' as the initial screen.

initialRouteName with array syntax route groups

When using array syntax like (foo,bar) to create multiple route groups, you can specify different initialRouteName values per group in unstable_settings. Use the group name as a key with an object containing initialRouteName. For example: bar: { initialRouteName: 'second' } targets the (bar) group.

Layout files as React components for flexible UI patterns

Layout files are just React components and can be used to display UI around, beside, or instead of navigators. This allows patterns like showing modals over the app, conditionally rendering different navigation structures, or displaying authentication-related UI.

Web modals feature availability and setup

Web modals are in alpha and available in SDK 54 and later. To use this feature, you must set the EXPO_UNSTABLE_WEB_MODAL=1 environment variable in your project for both development and export builds. You can do this by adding it to your .env file at the root of your project or by prefixing your commands, for example: EXPO_UNSTABLE_WEB_MODAL=1 npx expo start.

Clear bundler cache after configuration

After updating the Expo Router configuration, clear the bundler cache by running: npx expo start --clear (or the equivalent command for yarn, pnpm, or bun).

Remove outdated Yarn resolutions when upgrading Expo Router

When upgrading from an older version of Expo Router, remove all outdated Yarn resolutions or npm overrides from package.json. Specifically, remove metro, metro-resolver, and react-refresh resolutions.

Web support for Expo Router with Metro

To develop an Expo Router app for web, install react-native-web and react-dom dependencies. Then enable Metro web support by adding web.bundler set to 'metro' in the app config under app.json.

Babel configuration for Expo Router

Ensure babel.config.js uses 'babel-preset-expo' as the preset. If no custom Babel configuration is needed, the file can be deleted entirely.

Expo Router app.json configuration

Add a deep linking scheme and enable typed routes in app.json under the expo config: set scheme to 'your-app-scheme' and add experiments.typedRoutes set to true.

Automated migration for SDK 55 to 56

Run 'npx expo-codemod sdk-56-expo-router-react-navigation-replace src' to automatically migrate @react-navigation imports to expo-router entry points. Replace 'src' with the directory or glob containing your application code. Equivalent commands exist for yarn, pnpm, and bun.

Third-party libraries automatic import rewrite

In SDK 56, Expo CLI automatically rewrites @react-navigation imports that originate from node_modules to expo-router equivalents. This is a temporary compatibility shim to ease the transition. Application code is unaffected by this rewrite.

Disable automatic import rewriting with environment variable

To opt out of automatic React Navigation import rewriting, set the environment variable EXPO_ROUTER_DISABLE_RN_NAVIGATION_CHECK=1 before starting the bundler. This also disables the bundler error for application code that imports from @react-navigation/*. Example: 'EXPO_ROUTER_DISABLE_RN_NAVIGATION_CHECK=1 npx expo start'

React Navigation to Expo Router import migration table

Map React Navigation imports to Expo Router equivalents: | React Navigation source | Expo Router target | |---|---| | @react-navigation/native | expo-router/react-navigation | | @react-navigation/core | expo-router/react-navigation | | @react-navigation/elements | expo-router/react-navigation | | @react-navigation/routers | expo-router/react-navigation | | @react-navigation/stack | expo-router/js-stack | | @react-navigation/bottom-tabs | expo-router/js-tabs | | @react-navigation/material-top-tabs | expo-router/js-top-tabs | | @react-navigation/native-stack | No direct equivalent. Use the Stack layout instead. | | @react-navigation/drawer | No direct equivalent. Use the Drawer layout instead. |

Manual migration example for React Navigation imports

Before SDK 56: ```tsx import { ThemeProvider, DarkTheme } from '@react-navigation/native'; import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs'; ``` After SDK 56: ```tsx import { ThemeProvider, DarkTheme } from 'expo-router/react-navigation'; import { createMaterialTopTabNavigator } from 'expo-router/js-top-tabs'; ```

Root HTML file example with service worker in Expo Router

Example **src/app/+html.tsx** file showing root HTML configuration for Expo Router with service worker registration: The file imports ScrollViewStyleReset from 'expo-router/html' and accepts PropsWithChildren. It returns JSX with an html element containing head and body. The head includes meta tags for charset, X-UA-Compatible, and viewport. A script tag uses dangerouslySetInnerHTML to bootstrap the service worker. ScrollViewStyleReset disables body scrolling for native-like behavior. The body renders the children prop. This file only runs in Node.js during static rendering, not in the browser.

PWA manifest linking in Expo Router

To link a PWA manifest in Expo Router, add `<link rel="manifest" href="/manifest.json" />` in the head section of your **src/app/+html.tsx** file. The manifest.json should be located in the **public** directory.

Babel preset for Expo Router web

Expo Router uses the `babel-preset-expo` preset in **babel.config.js**. This preset is the default config and is needed for features like Expo constants access via process.env.APP_MANIFEST.

Bundler plugins migration to Expo Router

If you were using custom bundler plugins with @expo/webpack-config, see the Expo Metro config documentation for information on adding custom functionality to your bundler pipeline in Expo Router.

Output directory in Expo Router vs Webpack

In Expo Router, the output directory for production bundles is **dist**. In @expo/webpack-config, it was **web-build**.

Static directory in Expo Router vs Webpack

In Expo Router, the static directory for hosting static files is **public**. In @expo/webpack-config, it was **web**. Files from the public directory are served from the website's root (e.g., **public/favicon.ico** is served from https://example.com/favicon.ico) and are copied to the dist directory on build.

Config file in Expo Router vs Webpack

In Expo Router, the config file is **metro.config.js** with default config from @expo/metro-config. In @expo/webpack-config, it was **webpack.config.js** with default config from @expo/webpack-config.

Expo Router web output modes: static vs single

Expo Router supports two rendering patterns via the `web.output` setting. The recommended mode is `web.output: "static"` which outputs a new HTML file for each route and allows dynamically generating the entire HTML template using the **src/app/+html.tsx** file. The not recommended mode is `web.output: "single"` which outputs a single-page application and lets you use **public/index.html** as the template HTML file.

Export command for web production in Expo Router

In Expo Router, use `npx expo export --platform web` to bundle your website for production. The output goes to the **dist** directory. You can generate sourcemaps with the `--dump-sourcemap` flag. On build, the contents of the **public** directory will be copied to the **dist** directory.

Fast Refresh enabled by default in Expo Router

In Expo Router, Fast Refresh is enabled by default using the official Fast Refresh implementation by Meta. Unlike @expo/webpack-config, which required manual installation of @pmmmwh/react-refresh-webpack-plugin, no additional setup is needed.

Dev server hosting in Expo Router

In Expo Router, all platforms are hosted from the same dev server on the same port. This is convenient for emulating production behavior. All logs and hot module reloading go through the same port. Hosting with fake HTTPS is not currently supported due to native limitations.

Babel configuration platform detection in Expo Router

The root **babel.config.js** file is used for both web and native in Expo Router. You can detect the platform using `api.caller(caller => caller && caller.platform)` to apply platform-specific plugins. For example, set a web-only plugin by checking if `platform === 'web'`.

Expo constants in Expo Router

In Expo Router, the **expo-constants** library can be used to access the **app.json** in-app. This is accomplished using Babel with the `babel-preset-expo`, which sets `process.env.APP_MANIFEST` with the stringified contents of **app.json**. If you modify the **app.json**, restart the Babel cache with `npx expo start --clear` to see the updates.

Base URL and subpath hosting in Expo Router (experimental)

In Expo Router, you can use the experimental `baseUrl` field in the project's **app.json** to host from a subpath. Set it in `app.json` under `expo.experiments.baseUrl` (e.g., `"/evanbacon/my-website"`). Unlike @expo/webpack-config, this also updates the routing to account for the base path, so a route `/profile` with base path `/evanbacon/my-website` becomes `/evanbacon/my-website/profile`.

Service worker setup with Workbox in Expo Router

Expo Router doesn't have built-in service worker support, but Workbox can be used as a post-build step since Workbox doesn't require bundler transformation. Register a service worker in your HTML using **src/app/+html.tsx** by including a script that calls `navigator.serviceWorker.register('/sw.js')`. After building with `npx expo export -p web`, run Workbox CLI: `npx workbox-cli wizard` to configure it with `dist/` as the root, then `npx workbox-cli generateSW workbox-config.js` to generate the service worker config.

Service worker caching warnings for Expo Router web

Service workers can cause unexpected behavior on web if they aggressively cache content, preventing users from easily requesting updates. For the best offline mobile experience, create a native app with Expo instead. Unlike websites with service workers, native apps can be updated through the app store to clear cached experience.

PWA manifest configuration in Expo Router

Unlike @expo/webpack-config, Expo Router does not automatically generate a PWA manifest. Create one manually as **public/manifest.json** with the standard PWA manifest structure including short_name, name, icons, start_url, display, theme_color, and background_color. Link it in your **src/app/+html.tsx** using `<link rel="manifest" href="/manifest.json" />`.

Feature comparison: Expo Router vs @expo/webpack-config

Expo Router feature matrix compared to @expo/webpack-config: Bundle Splitting - Router: Yes (SDK 50, web), Webpack: Yes. Global CSS - Router: Yes (SDK 50, web), Webpack: Yes. CSS Modules - Router: Yes (SDK 50, web), Webpack: No. Static Font Optimization - Router: Yes (SDK 50, web), Webpack: No. API Routes - Router: Yes (SDK 50), Webpack: No. Multi-platform - Router: Yes, Webpack: No. Fast Refresh - Router: Yes, Webpack: No. Error Overlay - Router: Yes, Webpack: No. Lazy bundling - Router: Yes, Webpack: No. Static Generation - Router: Yes, Webpack: No. Environment Variables - Router: Yes, Webpack: No. tsconfig.json paths - Router: Yes, Webpack: No. Tree Shaking - Router: Partial support, Webpack: Yes.

CLI commands in Expo Router vs Webpack

CLI command differences between Expo Router and @expo/webpack-config: Start command - both use `npx expo start`. Bundle command - Router uses `npx expo export`, Webpack uses `npx expo export:web`. Output directory - Router uses **dist**, Webpack uses **web-build**.

@expo/webpack-config is deprecated

@expo/webpack-config is deprecated and not receiving any new feature updates. Expo Router is the recommended approach for all new Expo web projects.

Expo Router bundler uses Metro instead of Webpack

Expo Router uses a custom bundler stack based on Metro (the same bundler used by React Native), instead of Webpack 4 like @expo/webpack-config. This ensures maximum code reusability between web and native and solves forked behavior issues, but means certain Webpack bundling features may not be available in Expo Router yet.

Service worker registration example in Expo Router

Example service worker registration code for **src/app/+html.tsx** in Expo Router: Check if the browser supports service workers with `'serviceWorker' in navigator`. On load, call `navigator.serviceWorker.register('/sw.js')` to register the service worker at `/sw.js`. Handle the registration promise with `.then()` to log success and `.catch()` to handle errors.

React Navigation Elements library re-exported from expo-router/react-navigation

In SDK 56 and later, the React Navigation Elements library is re-exported from expo-router/react-navigation without requiring a separate package installation. Import components like Header and HeaderBackButton from expo-router/react-navigation.

SDK 56: Import paths changed from @react-navigation/* to expo-router/*

In SDK 56 and later, Expo Router stopped accepting application-code imports from @react-navigation/*. All imports now come from expo-router/* entry points instead. If upgrading from SDK 55 or earlier, follow the SDK 55 to 56 migration guide.

Do not return null from root component for loading states

It is bad practice and generally unsupported in Expo Router to return null from the root component while assets and fonts are loading. If you must defer rendering, do not attempt to navigate to any screens. On web, returning null from the root will cause static rendering to skip all children, resulting in no searchable content.

Navigation is always ready in Expo Router

In React Navigation, onReady is often used to determine when the splash screen should hide or when to track screens using analytics. In Expo Router, you can assume the navigation is always ready for navigation events. Use the Screen Tracking guide for migrating analytics and the Splash Screen feature for handling the splash screen.

Use ThemeProvider for setting theme instead of NavigationContainer

In React Navigation, theme is set for the entire app using the <NavigationContainer /> component. Expo Router manages the root container, so set the theme using ThemeProvider directly. Import ThemeProvider, DarkTheme, DefaultTheme, and useTheme from expo-router/react-navigation.

ThemeProvider can be used at any layer of the app

You can use ThemeProvider at any layer of the app to set the theme for a specific layout. The current theme can be accessed with the useTheme hook from expo-router/react-navigation.

Use Head component to set webpage title instead of documentTitle

To replace the NavigationContainer's documentTitle prop, use the Head component from Expo Router to set the webpage title.

Use layout settings to set initial routes for deep linking

In React Navigation, use the initialRouteName property of the linking configuration. In Expo Router, use layout settings instead.

Use SplashScreen from expo-router instead of expo-splash-screen

Expo Router wraps expo-splash-screen and adds special handling to ensure it is hidden after the navigation mounts and whenever an unexpected error is caught. Migrate from importing expo-splash-screen to importing SplashScreen from expo-router.

Reserved path /_flight/* for React Server Components

React Server Components use the /_flight/* path internally. Do not create routes or static files under this path.

favicon.ico can be safely overridden

Unlike the other reserved paths, /favicon.ico is safe to override. Expo CLI serves a default favicon when none is provided. You can replace it by placing a favicon.ico file in your public directory or by creating an API route.

Reserved path /_expo/* for internal middlewares

Expo Router uses the /_expo/* path for multiple internal middlewares, including dev tools and manifests. Do not create routes or static files under this path.

Reserved path /inspector for React Native debugger

React Native uses /inspector/debug and /inspector/network for the debugger. Avoid creating routes that match /inspector or its sub-paths.

Reserved path /expo-dev-plugins/* for development tool plugins

Expo development tool plugins use the /expo-dev-plugins/* path. Do not create routes or static files under this path.

Reserved path /manifest serves native app manifest

The dev server serves the native app manifest at the /manifest path. If you create a route at app/manifest.tsx, the dev server responds with manifest JSON instead of your page. Your route will appear to silently not load during development.

Reserved path /assets/* intercepts Metro bundled assets

Metro serves all bundled assets (images, fonts, and other files) at the /assets/* path. If you create a route at app/assets.tsx or a directory at public/assets/, Metro intercepts the request and your content is never reached. This applies to both top-level routes and static files. You should rename your route or directory to avoid the conflict, such as using app/media.tsx or public/images/logo.png instead.

Reserved path /_sitemap for auto-generated sitemap route

Expo Router automatically generates a sitemap route at the /_sitemap path for debugging. If you create a route at app/_sitemap.tsx, it will override the built-in sitemap. See the Sitemap reference for more details on this feature.

Reserved path /public/* conflicts with public directory

If your project has a public directory, the /public URL path may conflict with static file serving. Avoid creating a route at app/public.tsx or app/public/index.tsx since the path is implicitly reserved when the public directory exists.

Disable sitemap generation in app config

The sitemap can be removed by setting sitemap: false in the expo-router config plugin within the app.json configuration file.

Give your agent this brain