Expo Router

Expo Router maps files in app/ to routes.

app/
  _layout.tsx              -> root layout
  (tabs)/index.tsx         -> /
  (tabs)/settings.tsx      -> /settings
  story/[id].tsx           -> /story/123
  +not-found.tsx           -> not found route

Core Concepts

ConceptMeaning
app/Route root
_layout.tsxShared layout or navigator for a route segment
(group)/Organizes routes without adding the group name to the URL
[id].tsxDynamic route segment
+not-found.tsxNot-found screen
typed routesCompile-time route checking when experiments.typedRoutes is enabled
deep linksNative links map into the route tree

Route Group Example

import { Stack } from 'expo-router';

export default function AppLayout() {
  return <Stack />;
}

Place that in app/(app)/_layout.tsx to wrap every route in the group. The (app) folder does not appear in the URL.

Typed Routes

Enable typed routes in app config:

{
  "expo": {
    "experiments": {
      "typedRoutes": true
    }
  }
}

Testing Rules

  • Test route rendering with expo-router/testing-library when route behavior matters.
  • Assert path and params for dynamic routes.
  • Keep tests outside app/.
  • Smoke deep links before release when route URLs are part of notifications, emails, sharing, or web parity.

Gotcha: A route group changes file organization, not the URL. app/(tabs)/settings.tsx maps to /settings, not /(tabs)/settings.