rn-expo-router — guardrail for navigation in Expo + RN
For the current Expo API and per-version details, verify against the Expo docs / MCP
mcp.expo.dev/expo/skills(see rn-fundamentals → Source of truth).
The 4 rules (non-negotiable)
- Expo Router only. Never
importfrom@react-navigation/*directly — Expo Router wraps and owns it. - File-based: routes live in
app/. The filename IS the URL._layout.tsxfiles define the layout for their directory. - Typed routes ON. In
app.json:"expo": { "experiments": { "typedRoutes": true } }. UseHreftype for navigation, never raw strings. - Layouts contain navigators. Screen files contain only the screen UI. Tab bar / stack header config goes in
_layout.tsx.
Quick decision tree
- "Tabs / Stack / Drawer — which?" →
references/decision-tree.md - "How do I structure routes for an auth-gated section?" →
references/patterns.md(Auth groups) - "Deep linking from notification or URL?" →
references/deep-linking-setup.md - "Show me a real layout" →
references/examples/
Common anti-patterns (NEVER do)
- ❌
import { useNavigation } from '@react-navigation/native'→ useuseRouter()fromexpo-router. - ❌
router.push('/profile/123')as raw string → typed routes:router.push({ pathname: '/profile/[id]', params: { id: '123' } }). - ❌ Defining a
<Tabs.Screen>in a screen file — it goes in the parent_layout.tsx. - ❌ Hardcoded route strings scattered everywhere → use typed routes (
expo-router/typed-routesprovides static checking).
Sources
- Course: codewithbeto.dev/rnCourse — lesson 11 "Navigation Basics" (free) + 1 free Expo Router lesson.
- Official: https://docs.expo.dev/router/introduction/
- Official: https://docs.expo.dev/router/reference/typed-routes/