{"name":"expo-router","url":"https://github.com/expo/skills/tree/main/plugins/expo/skills/expo-router","install":"npx skills add expo/skills --skill expo-router","sdk":"expo","key":"expo/expo-router","description":"Framework (OSS). 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.","hasContent":true,"content":"---\nname: expo-router\ndescription: Framework (OSS). 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.\nversion: 1.0.1\nlicense: MIT\n---\n\n# Expo Router Navigation\n\nNavigation and routing for Expo Router apps. For screen styling, colors, controls, animations, media, and visual effects, use the `expo-native-ui` skill.\n\n## References\n\nConsult these resources as needed:\n\n```\nreferences/\n  route-structure.md     Route conventions, dynamic routes, groups, folder organization\n  tabs.md                NativeTabs, migration from JS tabs, iOS 26 features\n  toolbar-and-headers.md Stack headers and toolbar buttons, menus, search (iOS only)\n  form-sheet.md          Form sheets in expo-router: configuration, footers and background interaction.\n  search.md              Search bar with headers, useSearch hook, filtering patterns\n  zoom-transitions.md    Apple Zoom: fluid zoom transitions with Link.AppleZoom (iOS 18+)\n```\n\n## Code Style\n\n- Always use kebab-case for file names, e.g. `comment-card.tsx`\n- Always remove old route files when moving or restructuring navigation\n- Never use special characters in file names\n- Configure tsconfig.json with path aliases, and prefer aliases over relative imports for refactors.\n\n## Routes\n\nSee `./references/route-structure.md` for detailed route conventions.\n\n- Routes belong in the `app` directory.\n- Never co-locate components, types, or utilities in the app directory. This is an anti-pattern.\n- Ensure the app always has a route that matches \"/\", it may be inside a group route.\n\n## Library Preferences\n\n- `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.\n- In SDK 56+, never import from `@react-navigation/*` directly — use `expo-router/react-navigation` instead (covers `@react-navigation/native`, `/core`, `/elements`, `/routers`)\n\n## Behavior\n\n- Prefer `Stack.SearchBar` to add a search bar to a screen\n\n# Navigation\n\n## Link\n\nUse `<Link href=\"/path\" />` from 'expo-router' for navigation between routes.\n\n```tsx\nimport { Link } from 'expo-router';\n\n// Basic link\n<Link href=\"/path\" />\n\n// Wrapping custom components\n<Link href=\"/path\" asChild>\n  <Pressable>...</Pressable>\n</Link>\n```\n\nWhenever possible, include a `<Link.Preview>` to follow iOS conventions. Add context menus and previews frequently to enhance navigation.\n\n## Stack\n\n- ALWAYS use `_layout.tsx` files to define stacks\n- Use Stack from 'expo-router/stack' for native navigation stacks\n\n### Page Title\n\nSet the page title with `Stack.Title`:\n\n```tsx\n<Stack.Title>Home</Stack.Title>\n```\n\n## Context Menus\n\nAdd long press context menus to Link components:\n\n```tsx\nimport { Link } from \"expo-router\";\n\n<Link href=\"/settings\" asChild>\n  <Link.Trigger>\n    <Pressable>\n      <Card />\n    </Pressable>\n  </Link.Trigger>\n  <Link.Menu>\n    <Link.MenuAction\n      title=\"Share\"\n      icon=\"square.and.arrow.up\"\n      onPress={handleSharePress}\n    />\n    <Link.MenuAction\n      title=\"Block\"\n      icon=\"nosign\"\n      destructive\n      onPress={handleBlockPress}\n    />\n    <Link.Menu title=\"More\" icon=\"ellipsis\">\n      <Link.MenuAction title=\"Copy\" icon=\"doc.on.doc\" onPress={() => {}} />\n      <Link.MenuAction\n        title=\"Delete\"\n        icon=\"trash\"\n        destructive\n        onPress={() => {}}\n      />\n    </Link.Menu>\n  </Link.Menu>\n</Link>;\n```\n\n## Link Previews\n\nUse link previews frequently to enhance navigation:\n\n```tsx\n<Link href=\"/settings\">\n  <Link.Trigger>\n    <Pressable>\n      <Card />\n    </Pressable>\n  </Link.Trigger>\n  <Link.Preview />\n</Link>\n```\n\nLink preview can be used with context menus.\n\n## Modal\n\nPresent a screen as a modal:\n\n```tsx\n<Stack.Screen name=\"modal\" options={{ presentation: \"modal\" }} />\n```\n\nPrefer this to building a custom modal component.\n\n## Sheet\n\nPresent a screen as a dynamic form sheet:\n\n```tsx\n<Stack.Screen\n  name=\"sheet\"\n  options={{\n    presentation: \"formSheet\",\n    sheetGrabberVisible: true,\n    sheetAllowedDetents: [0.5, 1.0],\n    contentStyle: { backgroundColor: \"transparent\" },\n  }}\n/>\n```\n\n- Using `contentStyle: { backgroundColor: \"transparent\" }` makes the background liquid glass on iOS 26+.\n\n## Common route structure\n\nA standard app layout with tabs and stacks inside each tab:\n\n```\napp/\n  _layout.tsx — <NativeTabs />\n  (index,search)/\n    _layout.tsx — <Stack />\n    index.tsx — Main list\n    search.tsx — Search view\n```\n\n```tsx\n// app/_layout.tsx\nimport { NativeTabs } from \"expo-router/unstable-native-tabs\";\nimport { ThemeProvider, DarkTheme, DefaultTheme } from \"expo-router/react-navigation\";\nimport { useColorScheme } from \"react-native\";\n\nexport default function Layout() {\n  const colorScheme = useColorScheme();\n  return (\n    <ThemeProvider value={colorScheme === \"dark\" ? DarkTheme : DefaultTheme}>\n      <NativeTabs>\n        <NativeTabs.Trigger name=\"(index)\">\n          <NativeTabs.Trigger.Icon sf=\"list.dash\" md=\"list\" />\n          <NativeTabs.Trigger.Label>Items</NativeTabs.Trigger.Label>\n        </NativeTabs.Trigger>\n        <NativeTabs.Trigger name=\"(search)\" role=\"search\" />\n      </NativeTabs>\n    </ThemeProvider>\n  );\n}\n```\n\nCreate a shared group route so both tabs can push common screens:\n\n```tsx\n// app/(index,search)/_layout.tsx\nimport { Stack } from \"expo-router/stack\";\nimport { colors } from \"@/theme/colors\";\n\nexport default function Layout({ segment }) {\n  const screen = segment.match(/\\((.*)\\)/)?.[1]!;\n  const titles: Record<string, string> = { index: \"Items\", search: \"Search\" };\n\n  return (\n    <Stack\n      screenOptions={{\n        headerTransparent: true,\n        headerShadowVisible: false,\n        headerLargeTitleShadowVisible: false,\n        headerLargeStyle: { backgroundColor: \"transparent\" },\n        headerTitleStyle: { color: colors.label },\n        headerLargeTitle: true,\n        headerBlurEffect: \"none\",\n        headerBackButtonDisplayMode: \"minimal\",\n      }}\n    >\n      <Stack.Screen name={screen} options={{ title: titles[screen] }} />\n      <Stack.Screen name=\"i/[id]\" options={{ headerLargeTitle: false }} />\n    </Stack>\n  );\n}\n```\n\n## Submitting Feedback\nIf you encounter errors, misleading or outdated information in this skill, report it so Expo can improve:\n```bash\nnpx --yes submit-expo-feedback@latest --category skills --subject \"expo-router\" \"<actionable feedback>\"\n```\nOnly submit when you have something specific and actionable to report. Include as much relevant context as possible.\n","contentSource":"https://raw.githubusercontent.com/expo/skills/main/plugins/expo/skills/expo-router/SKILL.md","contentFetchedAt":"2026-07-28T23:15:38.912Z"}