Stop Maintaining Navigation Configs With Expo Router File Routing
Expo Router replaces centralized navigation configs with a file-based system under app/. Learn how layouts, dynamic segments and deep linking map to the file system and what breaks when you move files.
08 Apr 2026, 15:20 UTC

The navigation file that never stops growing
Traditional React Native apps centralize navigation in one large config. Screens, stacks, tabs and deep link mappings live together, so a rename or new feature creates merge conflicts and a mental gap between the file system and the app structure.
Expo Router moves the source of truth to the file system. A file under app/ is a route. Layouts are folders. The navigation state is derived from where files sit, not from a manually edited object.
How the file system maps to routes
Expo Router builds on React Navigation. It reads the app/ directory and creates stacks, tabs and drawers from folder structure and special files.
- Static routes.
app/settings.jsbecomes/settings. The path mirrors the relative path fromapp/. - Layouts.
app/_layout.jswraps all child routes. A layout can render a tab bar or header once and apply it to every nested screen. - Route groups. Folders wrapped in parentheses, e.g.
(auth), group files for organization without adding a URL segment.
File-based routing requires an Expo project set up with expo-router. The behavior is tied to the router version and the Expo SDK you use, so check compatibility before adopting.
Dynamic segments with bracket notation
Dynamic routes use bracket notation. app/user/[id].js matches /user/anything and captures the segment as a param.
Worked example: user profile
Create app/user/[id].js:
import { Text } from 'react-native';
import { useLocalSearchParams } from 'expo-router';
export default function UserProfile() {
const { id } = useLocalSearchParams();
return <Text>Viewing profile for user ID: {id}</Text>;
}
useLocalSearchParams reads params from the URL or from navigation. The param name comes from the file name [id].
Navigate with the Link component to avoid prop drilling:
import { Link } from 'expo-router';
<Link href="/user/123">Go to User 123</Link>
With TypeScript, the router can infer valid paths, which reduces typos. Without TypeScript the check is runtime only.
Deep linking is mapped, not magic
Because routes come from files, Expo Router can map a URL path to a screen. Deep linking still requires a URL scheme and host to be configured in your app config, typically app.json or expo.config.js. The scheme you define there is what the OS uses to open the app.
To check mapping, run the app with npx expo start from the project root. Required permission is a local dev server and a device or simulator. Once running, open a URL that matches a file path, e.g. YOUR_SCHEME://user/123, using the platform's URL open mechanism. Verify the app navigates to the correct screen and that useLocalSearchParams returns the expected value. Exact commands for opening URLs differ by OS and tooling version.
Risk: changing the file path changes the public URL. Renaming app/user/[id].js to app/profile/[id].js changes the reachable path from /user to /profile.
Trade-offs to plan for
Moving or renaming files immediately changes URLs. Existing links shared via email or push notifications can break. If URL stability matters, keep routes stable and use route groups for reorganization.
Shared state across deeply nested layouts can become implicit. State that must persist across multiple tab groups is defined by folder nesting rather than an explicit provider, which makes it harder to reason about.
Dynamic params are strings. Validate and parse them in the screen, and handle missing params to avoid rendering errors.
Check before shipping
- Path validation. Use
Linkto navigate and confirm the URL shown in development logs matches the file path. - Parameter check. In a bracketed route, log the result of
useLocalSearchParamsto confirm the segment is captured. - External trigger. Open the app via a custom URL with the configured scheme and verify it lands on the intended screen from a cold start.
File-based routing simplifies navigation by aligning it with project organization. It works best when the team treats app/ as a public API surface and avoids moving routes without considering deep link impact.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.