Pages, Routing & Navigation

Build the screens of your app with Expo Router: stacks, tabs, modals, deep links, protected routes, lists, forms and keyboard handling.

Screens are the pages of a mobile app. Expo Router gives you file-based routing: a file in app/ becomes a route, and layout files define stacks and tabs. This is the structure your agent will fill in screen by screen.

Core concepts

  1. File-based routes: app/index.tsx is the home route, app/settings.tsx is /settings, and app/post/[id].tsx is a dynamic route. Folders group routes and _layout.tsx files wrap them. — Expo Router intro
  2. Stacks, tabs and modals: A Stack pushes screens on top of each other, Tabs switch between top-level sections, and a modal presents a focused task. Combine them in nested layouts. — Expo Router docs
  3. Params and typed routes: Read dynamic values with useLocalSearchParams and navigate with router.push. Typed routes make wrong paths a compile error, which protects you from agent typos. — Expo Router docs
  4. Protected routes: Redirect signed-out users to a login screen from a layout, or use the router's protected-route support in recent versions. Keep the auth check in one place. — Expo Router authentication
  5. Lists done right: Use FlatList or Shopify's FlashList for long lists, give each row a stable key, and avoid rendering hundreds of views at once. — FlatList
  6. Forms and the keyboard: Handle keyboard overlap, input focus order, validation messages and submit states. Use a form library such as React Hook Form with a schema validator like Zod if forms grow. — KeyboardAvoidingView
  7. Deep links: Links like myapp://post/42 or a universal link open a specific screen. Plan routes so every important screen has a stable path. — Expo linking

Concept videos

YouTube channels and searches for these topics. On a large screen they open in the reading panel next to the roadmap.

Explanation

Draw the navigation map first

Before prompting, write the route tree: tabs at the top, stacks inside each tab, modals on top. Paste it into your prompt so the agent creates files in the right folders.

One place for auth redirects

Scattering if (!user) router.replace('/login') across screens causes flicker and bugs. Put the check in a layout so every child screen is protected consistently.

Empty, loading, error

Every data screen has four states: loading, empty, error and content. Ask the agent to implement all four, not only the happy path.

What Is It?

Routing decides which screen shows for which URL-like path, and navigation moves the user between screens.

Expo Router maps files in app/ to routes automatically.

Why Should I Care?

A clear route tree makes agent output predictable and makes deep links, auth gates and analytics straightforward later.

Real World Analogy

Routes are the floor plan of a building: lobby (index), floors (tabs), rooms (stack screens) and a private office (modal). Visitors need signs (links) to find each room.

Visual Mental Model

text
app/
  _layout.tsx (Stack)
  (tabs)/_layout.tsx (Tabs)
    index.tsx   explore.tsx   profile.tsx
  post/[id].tsx
  login.tsx  (modal)

Beginner Explanation

Create a tabs layout with Home, Explore and Profile, add one detail screen with a dynamic route, and ask your agent to add loading, empty and error states to every list.

Smallest Possible Example

tsx
import { Tabs } from 'expo-router';

export default function TabsLayout() {
  return (
    <Tabs screenOptions={{ headerShown: false }}>
      <Tabs.Screen name="index" options={{ title: 'Home' }} />
      <Tabs.Screen name="explore" options={{ title: 'Explore' }} />
      <Tabs.Screen name="profile" options={{ title: 'Profile' }} />
    </Tabs>
  );
}

Common Mistakes

❌ Putting data fetching and layout in one huge screen file.

Split into hooks and components so the agent edits small units.

❌ Using ScrollView with a long mapped list.

It renders everything at once. Use FlatList or FlashList.

❌ Hard-coding route strings everywhere.

Enable typed routes so mistakes are caught at compile time.

Real Project Example

Most Expo apps follow tabs-plus-stacks with a modal for create or sign-in flows; that pattern appears in Expo's own templates.

Build This Mini Project

Build a three-tab app with a detail route /item/[id], a login modal, and a redirect that sends signed-out users to login from the root layout.

Interview Question

How do you protect routes in Expo Router?

Check auth state in a shared layout and redirect or hide the protected group when the user is signed out, so every child screen inherits the protection.

Key Takeaways

  • Write the route tree before prompting.
  • Use layouts for tabs, stacks and auth checks.
  • Use FlatList or FlashList for lists.
  • Implement loading, empty and error states.

Stack for this step

LayerPickWhy
RoutingExpo RouterFile-based routes, typed paths, deep links.
ListsFlatList / FlashListVirtualised rendering.
FormsReact Hook Form + ZodValidation and submit state.

Prompts for Cursor, Claude Code & Codex

Paste these into Cursor, Claude Code, Codex, or any coding agent. Replace the bracketed parts with your app details, and keep the agent in plan mode first so you review the approach before it edits files.

Generate the route tree

text
From SPEC.md, propose an Expo Router route tree with tabs, stacks and modals. Output as a folder tree under app/ with one line per file describing its purpose. Do not create files yet.

Build a screen with all states

text
Create app/(tabs)/explore.tsx that lists items from useItems(). Implement loading skeletons, an empty state with a call to action, an error state with retry, and the content list with FlatList. Use components/ui only.

Auth gate

text
Add an auth gate in app/_layout.tsx: redirect to /login when there is no session, and to / after login. Keep the check in one place and avoid flicker by waiting for session loading.

Claude Code skill for this step

Save this as .claude/skills/expo-router-screen/SKILL.md in your project so Claude Code loads it automatically when the task matches. The same text works as a Cursor rule or an AGENTS.md section.

text
---
name: expo-router-screen
description: Use when creating routes, layouts or navigation in the Expo Router app.
---
1. Check the route tree in SPEC.md before creating files.
2. Create the route file in the right folder and use typed routes for navigation.
3. Implement loading, empty, error and content states.
4. Add the screen to the showcase or test file and run typecheck and lint.

Rules, databases & blogs to use

Resources

The 60-second story

Picture a building directory in a lobby. It lists every floor and room, and each room has a sign. You can walk straight to room 4B because the path is written down.

Expo Router makes the folder tree that directory. Create app/profile.tsx and the sign /profile exists. Tabs are floors, stacks are corridors, modals are private offices. The auth check is the security desk in the lobby: one place, everyone passes it.

Mental model: your folder tree is the building directory.

Threads in the same domain as this chapter — go deeper on iHateReading without leaving the roadmap.

How to build an AI chat app with Vercel AI SDK and Firebase cover

How to build an AI chat app with Vercel AI SDK and Firebase

Chat UI, streaming and backend wiring for an AI feature.

Expo new version SDK 52 cover

Expo new version SDK 52

What a real Expo SDK upgrade changes for app builders.