expo-router
SKILL.md
Expo Router
Overview
File-based routing for React Native using Expo Router 6.x. Maps file system structure in the app/ directory to navigation screens. Supports Stack and Tab navigators, route groups, dynamic parameters, and nested layouts.
Install: Included with Expo SDK 54+. Ensure expo-router is in dependencies.
Workflows
Setting up routing:
- Create
app/_layout.tsxas root layout (providers, global chrome) - Create route group directories:
app/(demo)/,app/(auth)/ - Add
_layout.tsxin each group for group-specific navigation - Add
index.tsxfor default screens - Add
[param].tsxfor dynamic routes - Add
+not-found.tsxfor 404 handling
Adding a new screen:
- Create file in appropriate route group
- Export default React component
- Configure screen options in parent
_layout.tsxor via<Stack.Screen options={...} /> - Navigate using
useRouter()or<Link>
Guidance
File Conventions
| File | Purpose |
|---|---|
_layout.tsx |
Layout wrapper for directory (providers, navigators) |
index.tsx |
Default screen for directory |
[param].tsx |
Dynamic route segment |
[...catchAll].tsx |
Catch-all route |
+not-found.tsx |
404 screen |
(group)/ |
Route group (no URL segment) |
Root Layout Pattern
The root _layout.tsx is the entry point. Use it for global providers:
app/_layout.tsx → GestureHandlerRootView > SafeAreaProvider > Context > Stack
Keep the root layout thin — push chrome (tabs, headers) into group layouts.
Route Groups
Route groups (name)/ organize screens without affecting the URL path. Common pattern:
app/
├── _layout.tsx # Root: providers + Stack
├── (demo)/
│ ├── _layout.tsx # Tabs or Stack for demo scenes
│ ├── index.tsx # Home screen
│ └── [id].tsx # Detail screen
└── +not-found.tsx
Navigation
- Programmatic:
const router = useRouter()→router.push('/detail/123'),router.back() - Declarative:
<Link href="/detail/123">component - Params:
const { id } = useLocalSearchParams<{ id: string }>() - Redirect:
<Redirect href="/login" />for conditional routing
Screen Options
Configure screen presentation via layout or inline:
- In layout:
<Stack.Screen name="detail" options={{ title: 'Detail', headerShown: false }} /> - Inline:
<Stack.Screen options={{ presentation: 'modal' }} /> - Common options:
title,headerShown,presentation('card' | 'modal'),animation
Layout Nesting
Nest providers in root, chrome in groups:
- Root
_layout.tsx:GestureHandlerRootView,SafeAreaProvider, theme context,<Stack /> - Group
_layout.tsx:<Tabs />or<Stack />with screen options, header configuration
Best Practices
- Keep route files thin — delegate to view components in
/components/views/ - Use route groups to separate concerns without affecting URLs
- Type route params with generics:
useLocalSearchParams<{ id: string }>() - Set
headerShown: falsewhen providing custom headers - Use
<Stack screenOptions={{ animation: 'slide_from_right' }} />for consistent transitions - Place shared providers (theme, data context) in root
_layout.tsx - Use
+not-found.tsxfor graceful 404 handling
Anti-Patterns
- Placing business logic in route files (keep them thin, delegate to components)
- Deeply nesting route groups beyond 2 levels
- Using React Navigation directly instead of Expo Router abstractions
- Hardcoding navigation paths as strings without a constants file for complex apps
- Forgetting to export default from route files (causes blank screens)
- Putting providers in group layouts when they should be in root layout
Weekly Installs
5
Repository
nguyenhuuca/assessmentGitHub Stars
17
First Seen
Feb 18, 2026
Security Audits
Installed on
mcpjam5
claude-code5
replit5
junie5
windsurf5
zencoder5