What is the App Router?
What is the App Router?
Section titled “What is the App Router?”Introduction
Section titled “Introduction”The App Router is Next.js’s modern routing paradigm, introduced as stable in Next.js 13.4. It is built on top of React Server Components and provides a file-system based routing system using an app/ directory. The App Router fundamentally changes how Next.js applications are structured by introducing a new set of file conventions, nested layouts, streaming, and built-in support for loading and error states.
Why do we need this?
Section titled “Why do we need this?”The Pages Router, while powerful, had limitations that became apparent as applications grew. Developers had to manually implement layouts, handle loading states with custom solutions, and manage error boundaries. The App Router solves these problems by providing a convention-based approach that makes these features first-class citizens.
Problem Statement
Section titled “Problem Statement”As a developer building complex Next.js applications, you need a routing system that:
- Supports nested layouts without manual composition
- Provides built-in loading and error states
- Leverages React Server Components for better performance
- Enables streaming for faster page loads
- Maintains intuitive file-system based routing
Real World Story
Section titled “Real World Story”Consider building a large SaaS platform like Notion or Figma. The application has a marketing site (public), a dashboard (authenticated), and a settings page (with its own sidebar). Each section needs its own layout, loading state, and error handling. With the Pages Router, you’d need to implement this manually. With the App Router, you simply create folders and files following the convention.
Real World Analogy
Section titled “Real World Analogy”Think of the App Router as a modular home construction system:
- The Pages Router is like building a house from scratch — you pour the foundation, frame the walls, install plumbing, and add electrical wiring manually
- The App Router is like using prefabricated room modules — each room comes with its own walls, floor, ceiling, and connections. You just stack them together
The layout.tsx file is the floor plan that stays the same across rooms. The page.tsx is the furniture you change for each room. The loading.tsx is the “under construction” sign.
Visual Explanation
Section titled “Visual Explanation”App Router Directory Structure:
app/├── layout.tsx ← Root layout (wraps everything)├── page.tsx ← Homepage (/)├── about/│ ├── layout.tsx ← About section layout│ └── page.tsx ← About page (/about)├── blog/│ ├── layout.tsx ← Blog layout (sidebar + content)│ ├── page.tsx ← Blog listing (/blog)│ └── [slug]/│ └── page.tsx ← Blog post (/blog/my-post)└── dashboard/ ├── layout.tsx ← Dashboard layout (requires auth) ├── page.tsx ← Dashboard home (/dashboard) ├── loading.tsx ← Loading spinner for dashboard └── error.tsx ← Error boundary for dashboardMermaid Diagram 1: App Router vs Pages Router
Section titled “Mermaid Diagram 1: App Router vs Pages Router”flowchart TD subgraph "Pages Router (pages/)" P[_app.tsx] --> P1[pages/index.tsx] P --> P2[pages/about.tsx] P --> P3[pages/blog/[slug].tsx] P1 --> L1[Manual Layout Wrapping] P2 --> L1 P3 --> L1 end
subgraph "App Router (app/)" A[app/layout.tsx] --> A1[app/page.tsx] A --> A2[app/about/page.tsx] A --> A3[app/blog/[slug]/page.tsx] A2 --> A4[app/about/layout.tsx] A4 --> A5[Nested Layout Auto] end
style P fill:#f59e0b,color:#000 style A fill:#7c3aed,color:#fff style L1 fill:#ef4444,color:#fff style A5 fill:#22c55e,color:#fffInternal Working
Section titled “Internal Working”When a request hits a Next.js App Router application:
- Request arrives — The server receives the incoming URL
- Route Resolution — Next.js parses the URL and matches it against the file system structure in
app/ - Layout Chain — All parent layouts above the matched route are collected and nested
- Component Tree — The page component is wrapped in its layout chain
- Rendering — Server Components render on the server, producing HTML and a stream of RSC payload
- Streaming — HTML is streamed to the client as it’s ready, starting with the shell (layouts) and progressively filling in content
- Hydration — Client Components are hydrated on the client to add interactivity
Mermaid Diagram 2: Request Lifecycle in App Router
Section titled “Mermaid Diagram 2: Request Lifecycle in App Router”sequenceDiagram participant B as Browser participant N as Next.js Server participant L as Layout Chain participant P as Page Component participant D as Database
B->>N: GET /blog/my-post N->>N: Parse URL → match route N->>L: Render root layout L-->>B: Stream root layout shell N->>L: Render blog layout L-->>B: Stream blog layout shell N->>P: Execute page component P->>D: Fetch data D-->>P: Return data P-->>B: Stream rendered page content B->>B: Hydrate Client ComponentsArchitecture
Section titled “Architecture”The App Router architecture follows a hierarchical component tree pattern:
RootLayout├── Header (shared)├── BlogLayout│ ├── Sidebar (shared within /blog)│ └── BlogPostPage│ ├── PostContent│ └── CommentsSection└── Footer (shared)Key architectural principles:
- File-based routing — Folders define route segments, files define UI
- Colocation — Place components, styles, tests, and data fetching near the routes they belong to
- Server-first — Components are Server Components by default, only sending JavaScript to the client when needed
- Progressive enhancement — Pages work without JavaScript and progressively gain interactivity
Mermaid Diagram 3: App Router Component Hierarchy
Section titled “Mermaid Diagram 3: App Router Component Hierarchy”flowchart TD RL[app/layout.tsx<br/>Root Layout] --> HP[app/page.tsx<br/>Homepage] RL --> AL[app/about/layout.tsx<br/>About Layout] RL --> BL[app/blog/layout.tsx<br/>Blog Layout] AL --> AP[app/about/page.tsx<br/>About Page] BL --> BP[app/blog/page.tsx<br/>Blog Listing] BL --> BD[app/blog/[slug]/page.tsx<br/>Blog Post] BL --> BS[app/blog/loading.tsx<br/>Blog Loading] BL --> BE[app/blog/error.tsx<br/>Blog Error]
style RL fill:#7c3aed,color:#fff style AL fill:#4f46e5,color:#fff style BL fill:#4f46e5,color:#fff style HP fill:#22c55e,color:#fff style AP fill:#22c55e,color:#fff style BP fill:#22c55e,color:#fff style BD fill:#22c55e,color:#fff style BS fill:#f59e0b,color:#000 style BE fill:#ef4444,color:#fffStep-by-Step Flow
Section titled “Step-by-Step Flow”Creating your first App Router route:
- Create an
app/directory in your project root - Add a
layout.tsxfile — this becomes the root layout - Add a
page.tsxfile — this becomes the homepage at/ - Create a folder
app/about/ - Add
page.tsxinsideabout/— this becomes/about - Add
layout.tsxinsideabout/— this nests inside the root layout - Run
npm run devand visit/and/about
Mermaid Diagram 4: Route Creation Flow
Section titled “Mermaid Diagram 4: Route Creation Flow”flowchart LR A[Create app/ directory] --> B[Add root layout.tsx] B --> C[Add root page.tsx] C --> D[Create app/about/ folder] D --> E[Add about/page.tsx] E --> F[Add about/layout.tsx] F --> G{Run dev server} G --> H[Visit / → Homepage] G --> I[Visit /about → About] H & I --> J[Routes Work!]Syntax
Section titled “Syntax”Basic App Router structure:
my-app/├── app/│ ├── layout.tsx # Required — Root layout│ ├── page.tsx # Homepage at /│ ├── about/│ │ └── page.tsx # /about│ └── blog/│ ├── page.tsx # /blog│ └── [slug]/│ └── page.tsx # /blog/my-post-slugBasic Example
Section titled “Basic Example”A simple App Router setup with two pages:
// app/layout.tsx — Root layout wraps all pagesexport default function RootLayout({ children,}: { children: React.ReactNode}) { return ( <html lang="en"> <body> <header> <nav> <a href="/">Home</a> <a href="/about">About</a> </nav> </header> <main>{children}</main> <footer>© 2024 My App</footer> </body> </html> )}// app/page.tsx — Homepageexport default function HomePage() { return ( <div> <h1>Welcome to My App</h1> <p>This is the homepage built with the App Router.</p> </div> )}// app/about/page.tsx — About pageexport default function AboutPage() { return ( <div> <h1>About Us</h1> <p>Learn more about our company and mission.</p> </div> )}What’s happening:
layout.tsxwraps every page inside it with the<html>,<body>,<header>, and<footer>page.tsxinsideapp/becomes the route/page.tsxinsideapp/about/becomes the route/about- The layout persists across navigation — only the page content changes
Intermediate Example
Section titled “Intermediate Example”Adding a nested layout for the blog section:
// app/blog/layout.tsx — Blog layout with sidebarexport default function BlogLayout({ children,}: { children: React.ReactNode}) { return ( <div className="blog-container"> <aside className="blog-sidebar"> <h2>Categories</h2> <ul> <li><a href="/blog?category=tech">Tech</a></li> <li><a href="/blog?category=design">Design</a></li> <li><a href="/blog?category=business">Business</a></li> </ul> </aside> <article className="blog-content"> {children} </article> </div> )}// app/blog/page.tsx — Blog listingexport default function BlogPage() { return ( <div> <h1>Blog Posts</h1> <div className="posts-grid"> <article> <h2>Getting Started with Next.js</h2> <p>Learn the basics of Next.js App Router...</p> </article> <article> <h2>Understanding Server Components</h2> <p>Deep dive into React Server Components...</p> </article> </div> </div> )}What’s happening:
- The blog layout provides a sidebar that persists when navigating between blog posts
- The
<aside>with categories stays mounted during navigation - Only the content inside
<article>changes when navigating between/blogand/blog/my-post
Advanced Example
Section titled “Advanced Example”Using the App Router with parallel routes and intercepting routes:
// app/layout.tsx — Root layout with parallel route slotsexport default function RootLayout({ children, modal,}: { children: React.ReactNode modal: React.ReactNode}) { return ( <html lang="en"> <body> {children} {modal} {/* Renders in parallel */} <div id="modal-root" /> </body> </html> )}// app/@modal/default.tsx — Default modal stateexport default function DefaultModal() { return null // No modal by default}Parallel routes (using @modal folder convention) allow rendering multiple pages in the same layout simultaneously — perfect for modals, side panels, and dashboards.
Production Example
Section titled “Production Example”Production App Router project structure:
my-saas-app/├── app/│ ├── layout.tsx # Root layout (analytics, fonts, metadata)│ ├── page.tsx # Landing page│ ├── loading.tsx # Global loading state│ ├── error.tsx # Global error boundary│ ├── not-found.tsx # Custom 404 page│ ├── (marketing)/ # Route group — no layout change│ │ ├── page.tsx # /marketing│ │ ├── features/│ │ │ └── page.tsx # /marketing/features│ │ └── pricing/│ │ └── page.tsx # /marketing/pricing│ ├── (dashboard)/ # Route group — dashboard layout│ │ ├── layout.tsx # Dashboard layout (auth required)│ │ ├── dashboard/│ │ │ └── page.tsx # /dashboard│ │ └── settings/│ │ └── page.tsx # /dashboard/settings│ └── api/│ └── auth/│ └── route.ts # API route: /api/authFolder Structure
Section titled “Folder Structure”my-nextjs-app/├── app/│ ├── layout.tsx # Root layout (required)│ ├── page.tsx # Homepage│ ├── loading.tsx # Global loading UI│ ├── error.tsx # Global error boundary│ ├── not-found.tsx # 404 page│ ├── globals.css # Global styles│ ├── favicon.ico # Site favicon│ ├── about/│ │ └── page.tsx # /about│ ├── blog/│ │ ├── layout.tsx # Blog layout with sidebar│ │ ├── page.tsx # /blog│ │ └── [slug]/│ │ └── page.tsx # /blog/hello-world│ └── api/│ └── hello/│ └── route.ts # API route: /api/hello├── components/ # Shared components│ ├── Header.tsx│ ├── Footer.tsx│ └── Sidebar.tsx├── lib/ # Utility functions│ ├── db.ts│ └── api.ts├── public/ # Static assets├── next.config.js # Next.js configuration└── package.json # Dependencies and scriptsBest Practices
Section titled “Best Practices”- Use route groups for organization — Wrap related routes in
(groupName)to organize without affecting the URL - Colocate components — Place route-specific components next to their route files
- Leverage nested layouts — Create layouts at each level of nesting for proper separation
- Default to Server Components — Only add
"use client"when you need interactivity, event handlers, or hooks - Keep layouts focused — Each layout should have a single responsibility (navigation, sidebar, footer)
- Use private folders — Prefix with
_folderNameto exclude from routing (for internal components)
Common Mistakes
Section titled “Common Mistakes”- Forgetting the root layout — Every App Router app needs at least
app/layout.tsxwith<html>and<body>tags - Putting
"use client"on layouts unnecessarily — Layouts can be Server Components and share data without client-side JavaScript - Not using the
childrenprop — Layouts must accept and render{children}to display nested pages - Mixing Pages and App Router in the same route — You can use both, but not for the same path
- Missing
default.tsxfor parallel routes — When using@modalor other parallel routes, provide a default fallback
Performance Notes
Section titled “Performance Notes”- Server Components by default — Reduces client-side JavaScript bundle size
- Automatic code splitting — Each route segment is automatically code-split
- Streaming — The App Router streams HTML from the server, improving perceived performance
- Partial rendering — Only the segment that changes re-renders during navigation (layouts persist)
- Prefetching — Links in the viewport are automatically prefetched for instant navigation
Security Notes
Section titled “Security Notes”- Server Components never reach the client — Sensitive logic and data stay on the server
- Automatic XSS protection — React’s built-in escaping protects against XSS attacks
- Route protection — Use middleware to protect routes at the edge before they render
- Environment variables — Use
NEXT_PUBLIC_prefix only for client-accessible variables
SEO Considerations
Section titled “SEO Considerations”- The App Router produces server-rendered HTML that search engines can crawl
- Use the
metadataAPI (notnext/head) for SEO tags in App Router - Nested layouts enable consistent meta tag inheritance
- Streaming improves Largest Contentful Paint (LCP) metrics
- Use
generateMetadatafor dynamic SEO based on route params
Interview Questions
Section titled “Interview Questions”- What is the App Router and how does it differ from the Pages Router?
- What are the special files in the App Router and what does each do?
- How does layout nesting work in the App Router?
- What advantage does the App Router have for performance?
- Can you use Pages Router and App Router in the same project?
-
Which file is required in every App Router project? a)
page.tsxb)layout.tsxc)loading.tsxd)error.tsxAnswer
b) `layout.tsx` — Every app needs a root layout with `` and `` tags. -
What does the
app/blog/[slug]/page.tsxfile represent? a) A blog listing page at /blog b) A dynamic blog post at /blog/:slug c) A blog category page d) An API endpointAnswer
b) A dynamic blog post at /blog/:slug — the `[slug]` folder creates a dynamic route segment. -
What is the default rendering behavior in the App Router? a) Client Components b) Server Components c) Static Site Generation d) Incremental Static Regeneration
Answer
b) Server Components — All components in the App Router are Server Components by default. -
How do you share a layout across multiple pages? a) Create a shared component and import it b) Use
layout.tsxin a common parent folder c) UseuseLayouthook d) Configure it in next.config.jsAnswer
b) Create `layout.tsx` in the parent folder — nested layouts automatically wrap child pages. -
What feature enables progressive HTML loading in the App Router? a) Static Generation b) Incremental Static Regeneration c) Streaming d) Client-side rendering
Answer
c) Streaming — The App Router streams HTML from the server as it becomes ready.
Practice Exercise
Section titled “Practice Exercise”- Create a new Next.js project with the App Router (
npx create-next-app@latest my-app) - Replace the default
pages/directory with anapp/directory - Create a root
layout.tsxwith:<html>,<body>, a<nav>with links, and a<footer> - Create pages for:
/,/about,/contact - Create a nested layout for
/blogwith a sidebar - Create a blog listing page at
/blogand a dynamic post page at/blog/[slug] - Run the dev server and verify all routes work
Mini Project
Section titled “Mini Project”Build a small company website with the App Router:
- Root layout: Header with logo + navigation, main content area, footer with copyright
- Homepage (
/): Hero section, featured services, call-to-action - About page (
/about): Company story, team section - Blog section (
/blog): Blog layout with category sidebar- Blog listing page showing post previews
- Blog post pages with dynamic slugs
- Contact page (
/contact): Contact form, address, map placeholder - Loading state: Add
loading.tsxfor the blog section - Error state: Add
error.tsxfor the blog section
Summary
Section titled “Summary”The App Router is Next.js’s modern routing system built on React Server Components. It uses file-system based routing with special files (layout.tsx, page.tsx, loading.tsx, error.tsx, not-found.tsx) to define the UI for each route segment. Key benefits include automatic nested layouts, built-in loading and error states, streaming, and Server Components by default. The App Router represents the future of Next.js development and is the recommended approach for new projects.
Cheat Sheet
Section titled “Cheat Sheet”# App Router File Conventionsapp/layout.tsx → Root layout (required)app/page.tsx → Homepage (/)app/about/page.tsx → /aboutapp/blog/[slug]/page.tsx → /blog/any-slug
# Key Benefits✅ Server Components by default✅ Nested layouts (auto-persist)✅ Built-in loading.tsx (Suspense)✅ Built-in error.tsx (Error Boundaries)✅ Streaming (progressive HTML)✅ Code splitting (per route)
# Route Groupsapp/(marketing)/page.tsx → / (URL unaffected)app/(dashboard)/page.tsx → / (URL unaffected)
# Private Foldersapp/_components/Header.tsx → Not a routeRelated Topics
Section titled “Related Topics”- Layouts and Templates (Next Topic)
- Dynamic Routes (Module 2)
- Route Groups (Module 2)
- Data Fetching (Phase 3)
- Streaming and Suspense