expo-router — Claude Code skill: navigation and routing
Skill for file-based routing, stacks, modals and tabs in Expo Router. Use it when building navigation in a React Native mobile app.
npx skills add expo/skills --skill expo-router -a claude-codeWhat expo-router does
expo-router teaches the assistant to work with file-based route structure, dynamic parameters, groups and nested stacks. The skill covers creating links with previews and context menus, setting up native Stack and NativeTabs, modals and form sheets, headers and search bars.
Includes reference guides for route structure, tabs, headers and toolbars, form sheets and search. Code style: kebab-case for file names, path aliases instead of relative imports, never colocate components in the app directory. Prefers Color from expo-router over raw PlatformColor; in SDK 56+, uses expo-router/react-navigation instead of direct imports from @react-navigation/*.
If your app runs SDK 56 or older, note that the skill references headerLargeTitleEnabled, while older versions need headerLargeTitle.
What it helps with
- set up file-based routing with groups and nested stacks
- add dynamic routes with parameters
- create native tabs with navigation between them
- present a screen as a modal or form sheet
- add a search bar to a screen header
Example prompts for the agent
- Create a screen with tabs at the bottom, each tab has its own route stack
- Add a link with preview and context menu to a product card
- Set up a dynamic route `/item/[id]` that accepts a URL parameter
How to install expo-router
1Skills CLI (Vercel)
npx skills add expo/skills --skill expo-router -a claude-code2Manually: put the files in place
~/.claude/skills/expo-router/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/expo-router/
1Skills CLI (Vercel)
npx skills add expo/skills --skill expo-router -a codex2Manually: put the files in place
.agents/skills/expo-router/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add expo/skills --skill expo-router -a cursor2Manually: put the files in place
.cursor/skills/expo-router/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install expo/skills expo-router2Manually: put the files in place
.github/skills/expo-router/SKILL.md1Skills CLI (Vercel)
npx skills add expo/skills --skill expo-router -a gemini-cli2Platform CLI
gemini skills install https://github.com/expo/skills --path plugins/expo/skills/expo-routerManually: put the files in place
.devin/skills/expo-router/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add expo/skills --skill expo-router -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
From the same set7
The whole set →Similar
Questions about expo-router
How do I install expo-router for Claude Code?
Run npx skills add expo/skills --skill expo-router -a claude-code, then run npx skills add expo/skills --skill expo-router -a claude-code, then open ~/.claude/skills/expo-router/SKILL.md.
What does expo-router do?
It's a skill that teaches the assistant how to build navigation in Expo apps. It covers routes, tabs, modals, links and search bars following Expo Router conventions.
What SDK version do I need?
The skill works across versions, but SDK 56+ renamed the option from headerLargeTitle to headerLargeTitleEnabled. For older versions, follow the documentation for your specific SDK.
Source text
SKILL.md · MIT
---
name: expo-router
description: Navigation and routing for Expo Router. Covers file-based routes, groups and dynamic routes, folder organization, Link with previews and context menus, native Stack, page titles, modals and form sheets, NativeTabs, headers and toolbars, and header search bars.
version: 1.0.1
license: MIT
---
# Expo Router Navigation
Navigation and routing for Expo Router apps. For screen styling, colors, controls, media, and visual effects, use the `expo-native-ui` skill; for motion and gestures, use `expo-animation`.
## References
Consult these resources as needed:
```
references/
route-structure.md Route conventions, dynamic routes, groups, folder organization
tabs.md NativeTabs, migration from JS tabs, iOS 26 features
toolbar-and-headers.md Stack headers and toolbar buttons, menus, search (iOS only)
form-sheet.md Form sheets in expo-router: configuration, footers and background interaction.
search.md Search bar with headers, useSearch hook, filtering patterns
zoom-transitions.md Apple Zoom: fluid zoom transitions with Link.AppleZoom (iOS 18+)
```
## Code Style
- Always use kebab-case for file names, e.g. `comment-card.tsx`
- Always remove old route files when moving or restructuring navigation
- Never use special characters in file names
- Configure tsconfig.json with path aliases, and prefer aliases over relative imports for refactors.
## Routes
See `./references/route-structure.md` for detailed route conventions.
- Routes belong in the `app` directory.
- Never co-locate components, types, or utilities in the app directory. This is an anti-pattern.
- Ensure the app always has a route that matches "/", it may be inside a group route.
## Library Preferences
- `Color` from `expo-router` for native semantic colors, not raw `PlatformColor` (type-safe, auto-adapts to light/dark). See `expo-native-ui` for the full color palette pattern.
- In SDK 56+, never import from `@react-navigation/*` directly — use `expo-router/react-navigation` instead (covers `@react-navigation/native`, `/core`, `/elements`, `/routers`)
## Behavior
- Prefer `Stack.SearchBar` to add a search bar to a screen
# Navigation
## Link
Use `<Link href="/path" />` from 'expo-router' for navigation between routes.
```tsx
import { Link } from 'expo-router';
// Basic link
<Link href="/path" />
// Wrapping custom components
<Link href="/path" asChild>
<Pressable>...</Pressable>
</Link>
```
Whenever possible, include a `<Link.Preview>` to follow iOS conventions. Add context menus and previews frequently to enhance navigation.
## Stack
- ALWAYS use `_layout.tsx` files to define stacks
- Use Stack from 'expo-router/stack' for native navigation stacks
### Page Title
Set the page title with `Stack.Title`:
```tsx
<Stack.Title>Home</Stack.Title>
```
## Context Menus
Add long press context menus to Link components:
```tsx
import { Link } from "expo-router";
<Link href="/settings" asChild>
<Link.Trigger>
<Pressable>
<Card />
</Pressable>
</Link.Trigger>
<Link.Menu>
<Link.MenuAction
title="Share"
icon="square.and.arrow.up"
onPress={handleSharePress}
/>
<Link.MenuAction
title="Block"
icon="nosign"
destructive
onPress={handleBlockPress}
/>
<Link.Menu title="More" icon="ellipsis">
<Link.MenuAction title="Copy" icon="doc.on.doc" onPress={() => {}} />
<Link.MenuAction
title="Delete"
icon="trash"
destructive
onPress={() => {}}
/>
</Link.Menu>
</Link.Menu>
</Link>;
```
## Link Previews
Use link previews frequently to enhance navigation:
```tsx
<Link href="/settings">
<Link.Trigger>
<Pressable>
<Card />
</Pressable>
</Link.Trigger>
<Link.Preview />
</Link>
```
Link preview can be used with context menus.
## Modal
Present a screen as a modal:
```tsx
<Stack.Screen name="modal" options={{ presentation: "modal" }} />
```
Prefer this to building a custom modal component.
## Sheet
Present a screen as a dynamic form sheet:
```tsx
<Stack.Screen
name="sheet"
options={{
presentation: "formSheet",
sheetGrabberVisible: true,
sheetAllowedDetents: [0.5, 1.0],
contentStyle: { backgroundColor: "transparent" },
}}
/>
```
- Using `contentStyle: { backgroundColor: "transparent" }` makes the background liquid glass on iOS 26+.
## Common route structure
A standard app layout with tabs and stacks inside each tab:
```
app/
_layout.tsx — <NativeTabs />
(index,search)/
_layout.tsx — <Stack />
index.tsx — Main list
search.tsx — Search view
```
```tsx
// app/_layout.tsx
import { NativeTabs } from "expo-router/unstable-native-tabs";
import { ThemeProvider, DarkTheme, DefaultTheme } from "expo-router/react-navigation";
import { useColorScheme } from "react-native";
export default function Layout() {
const colorScheme = useColorScheme();
return (
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
<NativeTabs>
<NativeTabs.Trigger name="(index)">
<NativeTabs.Trigger.Icon sf="list.dash" md="list" />
<NativeTabs.Trigger.Label>Items</NativeTabs.Trigger.Label>
</NativeTabs.Trigger>
<NativeTabs.Trigger name="(search)" role="search" />
</NativeTabs>
</ThemeProvider>
);
}
```
Create a shared group route so both tabs can push common screens:
```tsx
// app/(index,search)/_layout.tsx
import { Stack } from "expo-router/stack";
import { colors } from "@/theme/colors";
export default function Layout({ segment }) {
const screen = segment.match(/\((.*)\)/)?.[1]!;
const titles: Record<string, string> = { index: "Items", search: "Search" };
return (
<Stack
screenOptions={{
headerTransparent: true,
headerShadowVisible: false,
headerLargeTitleShadowVisible: false,
headerLargeStyle: { backgroundColor: "transparent" },
headerTitleStyle: { color: colors.label },
headerLargeTitleEnabled: true,
headerBlurEffect: "none",
headerBackButtonDisplayMode: "minimal",
}}
>
<Stack.Screen name={screen} options={{ title: titles[screen] }} />
<Stack.Screen name="i/[id]" options={{ headerLargeTitleEnabled: false }} />
</Stack>
);
}
```
`headerLargeTitleEnabled` is the SDK 56+ option name; older SDKs use `headerLargeTitle`, which is deprecated upstream.
## Submitting Feedback
If you encounter errors, misleading or outdated information in this skill, report it so Expo can improve:
```bash
npx --yes @expo/agent-cli@latest feedback --category skills --subject "expo-router" "<actionable feedback>"
```
Only submit when you have something specific and actionable to report. Include as much relevant context as possible.
If an agent repeatedly fails at an Expo task or the user has to step in, submit a brief report of the task, expected result, and what went wrong using `--category evals` and the relevant Expo package or command as `--subject`.
© expo · MIT · expo/skills