Skip to content

/mobile-navigation-expo-router

File-based routing and navigation for Expo/React Native

shell
$ npx -y skills add agents-inc/skills --skill mobile-navigation-expo-router --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/mobile-navigation-expo-router
How auto-invocation works

Context preview

The summary Claude sees to decide when to auto-load this skill.

File-based routing and navigation for Expo/React Native

SKILL.md

mobile-navigation-expo-router.SKILL.md
name: mobile-navigation-expo-router
description: File-based routing and navigation for Expo/React Native

Expo Router Patterns

> **Quick Guide:** File-based routing for React Native and web. Files in `app/` become routes automatically. Use `_layout.tsx` for navigation structure (Stack, Tabs), groups `(name)/` for URL-invisible organization, `[param]` for dynamic segments. SDK 53+: use `Stack.Protected` with a `guard` prop for authentication. Enable `typedRoutes` for compile-time route safety. API routes use `+api.ts` suffix.

---

<critical_requirements>

CRITICAL: Before Using This Skill

> **All code must follow project conventions in CLAUDE.md** (kebab-case, named exports, import ordering, `import type`, named constants)

**(You MUST define navigation structure in `_layout.tsx` files -- screens without a layout parent default to a basic Stack)**

**(You MUST use `Stack.Protected` with `guard` prop for authentication flows in SDK 53+ -- NOT imperative redirects in useEffect)**

**(You MUST use `useLocalSearchParams` for route params in screens -- `useGlobalSearchParams` causes unnecessary re-renders on unfocused screens)**

**(You MUST enable `typedRoutes` in app.json experiments for compile-time route validation -- catches invalid navigation at build time)**

</critical_requirements>

---

**Auto-detection:** expo-router, Expo Router, file-based routing, _layout.tsx, Stack.Screen, Tabs.Screen, useRouter, useLocalSearchParams, useSegments, usePathname, Link href, router.push, router.replace, router.dismiss, router.dismissTo, +api.ts, +not-found, Stack.Protected, generateStaticParams, expo-router/head, Slot, Redirect, useFocusEffect, NativeTabs, headless tabs, TabSlot, TabTrigger

**When to use:**

  • Setting up file-based navigation in an Expo app
  • Implementing authentication flows with route protection
  • Creating tab, stack, or modal navigation layouts
  • Building API routes for server-side logic
  • Configuring typed routes for compile-time safety
  • Adding deep linking and static rendering for web

**Key patterns covered:**

  • File convention: `_layout.tsx`, `[param]`, `[...slug]`, `(group)/`, `+api.ts`, `+not-found.tsx`
  • Layout navigators: Stack, Tabs, headless tabs, native tabs
  • Authentication: `Stack.Protected` guard pattern (SDK 53+), redirect pattern (SDK 52)
  • Navigation hooks: `useRouter`, `useLocalSearchParams`, `useSegments`, `usePathname`
  • API routes with standard Request/Response
  • Typed routes with auto-generated TypeScript definitions
  • Modal routes, shared routes between tabs, nested navigation

**When NOT to use:**

  • Apps that need fully custom native navigation controllers beyond what React Navigation provides
  • Simple single-screen apps with no navigation
  • Web-only projects where a web-native router is more appropriate

---

<philosophy>

Philosophy

Expo Router maps the filesystem to your navigation hierarchy. Every file in `app/` is a route; every `_layout.tsx` defines how its sibling routes are presented (stack, tabs, drawer). This convention-over-configuration approach means:

1. **URLs are first-class** -- every screen has a URL, enabling deep linking on mobile and SEO on web without extra configuration 2. **Layouts are composable** -- nest `_layout.tsx` files to create any navigation structure (tabs containing stacks containing modals) 3. **The file tree IS the sitemap** -- new developers understand navigation by reading the directory structure, not a central config 4. **Universal by default** -- the same route definitions work on iOS, Android, and web

**Mental model:** Think of `app/` as a website. `_layout.tsx` files are the "chrome" (nav bars, tab bars). Route files are the "pages." Groups `(name)/` organize without affecting URLs. This maps directly to how web routing works, which is intentional -- Expo Router is built on top of React Navigation but presents a web-like API.

</philosophy>

---

<patterns>

Core Patterns

Pattern 1: File Conventions

Every file in `app/` maps to a route. Special characters change behavior:

| File | URL | Purpose | |------|-----|---------| | `index.tsx` | `/` (or parent path) | Default route for directory | | `about.tsx` | `/about` | Static route | | `[id].tsx` | `/:id` | Dynamic segment | | `[...slug].tsx` | `/a/b/c` | Catch-all segments | | `_layout.tsx` | N/A | Wraps sibling routes in navigator | | `(group)/` | Not in URL | Organizes routes without URL impact | | `+not-found.tsx` | N/A | 404 fallback for unmatched routes | | `+api.ts` | Server endpoint | API route handler | | `+html.tsx` | N/A | Root HTML wrapper (web static rendering) |

**Key insight:** Groups `(name)/` are purely organizational. `(tabs)/home.tsx` and `home.tsx` both resolve to `/home`. Use groups to apply different layouts to different route sets without changing URLs.

> Full directory structure examples: [examples/core.md](examples/core.md)

---

Pattern 2: Layout Routes

`_layout.tsx` files wrap their sibling routes in a navigator. The layout determines HOW routes are presented (stack push, tab switch, modal overlay).

// app/_layout.tsx -- Root layout wrapping entire app
import { Stack } from "expo-router";

export default function RootLayout() {
  return (
    <Stack>
      <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
      <Stack.Screen name="modal" options={{ presentation: "modal" }} />
      <Stack.Screen name="+not-found" />
    </Stack>
  );
}

**Why this matters:** Without a `_layout.tsx`, routes get a default Stack navigator with default headers. Always define layouts explicitly for control over headers, transitions, and navigation structure.

**Gotcha:** The `name` prop in `Stack.Screen`/`Tabs.Screen` must match the filename (without extension) or directory name exactly. `name="(tabs)"` matches the `(tabs)/` directory.

> Full layout examples (tabs, nested stacks, drawers): [examples/core.md](examples/core.md)

---

Pattern 3: Navigation Hooks

import {
Read more
Read it on GitHub ↗

Showing the first part of this file.

Ships withagents-inc-skills

The official skills marketplace for Agents Inc. 150+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?

Get the whole plugin, auto-invoked