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
| Concept | Meaning |
|---|---|
app/ | Route root |
_layout.tsx | Shared layout or navigator for a route segment |
(group)/ | Organizes routes without adding the group name to the URL |
[id].tsx | Dynamic route segment |
+not-found.tsx | Not-found screen |
| typed routes | Compile-time route checking when experiments.typedRoutes is enabled |
| deep links | Native 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-librarywhen 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.tsxmaps to/settings, not/(tabs)/settings.