Expo Router is the standard way to structure navigation in modern Expo apps. These are the patterns agents should follow.
Core concepts
- Root layout:
app/_layout.tsxwraps the whole app. Put providers (query client, theme, auth) and the global Stack here, and import your global CSS once. — Expo Router docs - Route groups: Folders in parentheses such as
(tabs)or(auth)group routes without changing the URL. Use them to separate signed-in and signed-out screens. — Expo Router docs - Dynamic routes:
[id].tsxcaptures a value. Read it withuseLocalSearchParams<{ id: string }>(), and validate it before use. — Expo Router docs - Modals: A route can present as a modal via screen options in the Stack layout, which suits create, filter and sign-in flows. — Expo Router docs
Concept videos
YouTube channels and searches for these topics. On a large screen they open in the reading panel next to the roadmap.
- Expo Router deep dive — Expo channel
Explanation
Typed routes
Turn on typed routes in app config and use Href types so navigating to a route that does not exist fails at compile time rather than at runtime.
Where state lives
Keep screens thin: they read hooks and render components. Navigation state belongs to the router, business state to your store or query cache.
What Is It?
Expo Router is a file-system router built on React Navigation that gives Expo apps URL-like paths for every screen.
Why Should I Care?
Deep links, web support and agent-friendly structure all come from one consistent routing convention.
Real World Analogy
It is a postal system where each file name is an address and layouts are the sorting offices that decide what wraps each delivery.
Visual Mental Model
_layout.tsx wraps -> (group)/_layout.tsx wraps -> screen.tsxSmallest Possible Example
import { useLocalSearchParams, router } from 'expo-router';
import { Text, Pressable } from 'react-native';
export default function PostScreen() {
const { id } = useLocalSearchParams<{ id: string }>();
return (
<Pressable onPress={() => router.back()}>
<Text>Post {id}</Text>
</Pressable>
);
}Common Mistakes
❌ Trusting route params blindly.
Params are strings from a link and may be missing or malicious; validate them.
❌ Wrapping every screen in its own provider.
Providers belong in layouts so they mount once.
Build This Mini Project
Create (auth) and (tabs) groups, a dynamic /post/[id] route, and a modal route for creating a post.
Prompts for Cursor, Claude Code & Codex
Paste these into Cursor, Claude Code, Codex, or any coding agent. Replace the bracketed parts with your app details, and keep the agent in plan mode first so you review the approach before it edits files.
Refactor into groups
Reorganise app/ into (auth) and (tabs) route groups with the correct layouts. Keep URLs unchanged, update imports, enable typed routes, and run typecheck.Param validation
Add param validation to app/post/[id].tsx using zod: show a not-found state for invalid ids and never call the API with an invalid id.Rules, databases & blogs to use
- Expo Router rule: router conventions

