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