expo-router

作成者: expo

フレームワーク(OSS)。Expo Routerのナビゲーションとルーティング。ファイルベースのルート、グループと動的ルート、フォルダ構成、プレビューとコンテキストメニュー付きのLink、ネイティブStack、ページタイトル、モーダルとフォームシート、NativeTabs、ヘッダーとツールバー、ヘッダー検索バーをカバー。

npx skills add https://github.com/expo/skills --skill expo-router

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

Link

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

Link Previews

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

Submitting Feedback

If you encounter errors, misleading or outdated information in this skill, report it so Expo can improve:

npx --yes submit-expo-feedback@latest --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.

expoのその他のスキル

expo-upgrade
expo
フレームワーク(OSS)。Expo SDKのバージョンアップグレードと依存関係の問題修正のためのガイドライン
apidevelopmentofficial
expo-data-fetching
expo
Framework (OSS). Use when implementing or debugging ANY network request, API call, or data fetching. Covers fetch API, React Query, SWR, error handling, caching, offline support, and Expo Router data loaders (`useLoaderData`).
official
android-e2e-testing
expo
Androidエミュレーター上でADBを使用してExpo Routerの機能をテストします。ネイティブAndroid機能を実装した後や、AndroidでのUI動作を確認する際に使用してください。
official
expo-dev-client
expo
EAS Buildまたはローカルで、実機上でネイティブコードをテストするためのカスタムExpo開発クライアントを構築します。カスタムネイティブモジュール、Appleターゲット(ウィジェット、アプリクリップ)、またはExpo Goに含まれないサードパーティのネイティブコードを使用する場合にのみ必要です。まずはnpx expo startでExpo Goをお試しください。自動TestFlight提出によるクラウドビルド、またはお使いのマシンでのローカルビルドをサポートし、.ipa(iOS)または.apk/.aab(Android)ファイルを出力します。eas.jsonに、設定を行う開発プロファイルを含む構成が必要です。
official
expo-tailwind-setup
expo
Expoアプリ向けのiOS、Android、Web対応ユニバーサルTailwind CSS v4スタイリング。Metroトランスフォーマーを介してTailwind CSS v4をreact-native-cssおよびNativeWind v5と統合し、Babel設定を不要にします。classNameスタイルをネイティブ要素に適用する再利用可能なCSSラップコンポーネントライブラリ(View、Text、ScrollView、Pressable、TextInput、Image、Link)を提供。CSSメディアクエリによるプラットフォーム固有のスタイリング、@themeブロックによるカスタムテーマ変数、Appleセマンティック...をサポートします。
official
android-jetpack-compose
expo
Jetpack Composeを使用してAndroid UIを構築する際、remember/mutableStateOfで状態を管理する場合、または宣言的UIパターンを実装する場合に使用します。
official
swiftui-expert-skill
expo
SwiftUIコードの作成、レビュー、改善を行い、状態管理、ビュー構成、パフォーマンス、macOS固有のAPI、iOS 26+のLiquid…に関するベストプラクティスに従います。
official
eas-update-insights
expo
公開されたEASアップデートの健全性を確認:クラッシュ率、インストール/起動数、ユニークユーザー、ペイロードサイズ、埋め込み型とOTAユーザーの内訳など。
official