TutorialsNext.jsRouting with the App Router
Next.js

Routing with the App Router

The App Router uses folders to define routes. Special files inside each folder add behavior to that route segment.

Special files

app/
  layout.tsx     → shared UI wrapping child routes (persists across navigation)
  page.tsx       → the route's unique UI
  loading.tsx    → shown while the segment loads (Suspense fallback)
  error.tsx      → error boundary for the segment
  not-found.tsx  → 404 UI for the segment
  route.ts       → API endpoint (instead of page.tsx)

Dynamic routes

Wrap a folder name in square brackets to capture a URL parameter:

// app/blog/[slug]/page.tsx
export default async function BlogPost({
  params,
}: {
  params: Promise<{ slug: string }>;
}) {
  const { slug } = await params;
  return <h1>Post: {slug}</h1>;
}
💡

In current Next.js, params and searchParams are Promises — you must await them.

Linking between pages

Use the <Link> component for client-side navigation (no full page reload). It also prefetches linked pages in the background.

import Link from "next/link";

<Link href="/about">About</Link>
<Link href={`/blog/${post.slug}`}>{post.title}</Link>

Layouts

A layout.tsx wraps all pages within its folder and persists across navigation (it doesn't re-mount). The root layout is required and must define <html> and <body>.

// app/layout.tsx
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <nav>My Site</nav>
        {children}
      </body>
    </html>
  );
}

Layouts nest automatically — a layout deeper in the tree renders inside its parent layout.

Watch & Learn

A recommended video to watch alongside this chapter.

More “Routing with the App Router” videos on YouTube