Catalog
expo/expo-router

expo

expo-router

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.

global
New~1.6k
v1.0Saved Jul 11, 2026

Expo Router Navigation

Navigation and routing for Expo Router apps. For screen styling, colors, controls, animations, media, and visual effects, use the expo-native-ui skill.

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

Use <Link href="/path" /> from 'expo-router' for navigation between routes.

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:

<Stack.Title>Home</Stack.Title>

Context Menus

Add long press context menus to Link components:

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>;

Use link previews frequently to enhance navigation:

<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:

<Stack.Screen name="modal" options={{ presentation: "modal" }} />

Prefer this to building a custom modal component.

Sheet

Present a screen as a dynamic form sheet:

<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
// 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:

// 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 },
        headerLargeTitle: true,
        headerBlurEffect: "none",
        headerBackButtonDisplayMode: "minimal",
      }}
    >
      <Stack.Screen name={screen} options={{ title: titles[screen] }} />
      <Stack.Screen name="i/[id]" options={{ headerLargeTitle: false }} />
    </Stack>
  );
}
Files8
8 files · 43.3 KB

Select a file to preview

Overall Score

87/100

Grade

A

Excellent

Safety

90

Quality

88

Clarity

89

Completeness

82

Summary

This skill provides comprehensive guidance on Expo Router navigation and routing, covering file-based routes, Links with previews/context menus, native Stacks, modals, form sheets, NativeTabs, headers/toolbars, and search bars. It includes detailed reference documents and code examples for structuring Expo apps with modern navigation patterns.

Detected Capabilities

code example documentationfile path and directory structure guidancecomponent API documentationplatform-specific feature guidance (iOS/Android)TypeScript type hints in examples

Trigger Keywords

Phrases that MCP clients use to match this skill to user intent.

expo router navigationnative tabs setupfile-based routesstack headers iosform sheet modalssearch bar implementationlink previewszoom transitions ios

Referenced Domains

External domains referenced in skill content, detected by static analysis.

developer.apple.comdocs.expo.devexample.com

Use Cases

  • /Creating file-based route structures with groups and dynamic routes
  • Implementing native tabs with semantic roles and iOS 26+ features
  • Adding search bars to headers with filtering and debouncing patterns
  • Building form sheets with footers and interactive background content
  • Wiring up Link navigation with previews and context menus
  • Setting up Stack headers, toolbars, and toolbar menus (iOS)
  • Implementing Apple Zoom fluid transitions for image galleries
  • Migrating from JavaScript tabs to native tab implementations

Quality Notes

  • Excellent clarity: well-organized sections with clear headings, code examples for every major pattern, and visual hierarchy
  • Comprehensive completeness: six reference files cover all major navigation patterns, limitations explicitly documented (e.g., iOS-only features, SDK version requirements)
  • Strong code examples: practical, runnable code with edge cases addressed (e.g., Stack.Toolbar component wrapping rules, safe area handling in SDK 55+)
  • Platform-aware guidance: clearly notes iOS vs Android differences (e.g., Native Tabs max 5 on Android, liquid glass on iOS 26+), SDK version compatibility tables
  • Error handling well-covered: common issues section in tabs.md lists 7 frequent problems with solutions (icons not showing, headers missing, trigger name mismatches)
  • Library preference guidelines: explicitly prefers Color over PlatformColor, Stack.SearchBar over alternatives, SF Symbols over vector icons, reducing ambiguity
  • Edge cases addressed: handles empty search states, debounced search, drag dismissal gesture conflicts, sheet detent positioning with interactive background
  • Limitations clearly marked: form sheet footer positioning requires flex: 1, toolbar components must be wrapped in Stack.Toolbar parent, dynamic tab addition remounts navigator
  • Style consistency enforced: kebab-case file names, no co-location of components in app directory, path aliases over relative imports
  • Self-contained documentation: all referenced files present (form-sheet.md, route-structure.md, search.md, tabs.md, toolbar-and-headers.md, zoom-transitions.md)
Model: claude-haiku-4-5-20251001Analyzed: Jul 11, 2026

Reviews

Add this skill to your library to leave a review.

No reviews yet

Be the first to share your experience.

Add expo/expo-router to your library

Command Palette

Search for a command to run...