Routing in the App Router
Folders = routes, special files, dynamic segments.
Updated
What Next.js is
Next.js is a framework on top of React. React gives you components; Next adds everything a real app needs:
| What Next adds | Without Next you'd have to... |
|---|---|
| folder-based routing | configure a router by hand |
| server rendering (SSR, static, PPR) | ship just an empty page + JS on the client |
| Server Components and Server Actions | write a separate backend |
| caching, image and font optimization | configure them yourself |
| an optimized build and deploy (Vercel) | configure the bundler, server, CDN |
Next has two routing systems: the App Router (app/, modern — the one we use) and the Pages Router (pages/, old).
What file-based routing is
Routing = which code answers which URL. In the App Router, the folder structure inside app/ is the URL structure. A route becomes reachable when the folder has a page.tsx.
app/layout.tsxthe shared layout for the whole site (required)page.tsx/blog/page.tsx/blog[slug]/page.tsx/blog/:slug, e.g. /blog/hello
(marketing)/about/page.tsx/about — the (marketing) group doesn't appear in the URL
_components/ignored by routing (a private folder)
The special files
| File | Role |
|---|---|
page.tsx |
the route's UI — makes it public |
layout.tsx |
wraps the child pages; persists across navigation |
loading.tsx |
a Suspense fallback while the page loads |
error.tsx |
catches errors in the segment (a Client Component) |
not-found.tsx |
shown on notFound() or a 404 |
route.ts |
an API endpoint (GET, POST...) — see Route Handlers |
Details on layouts and states in Layouts and navigation.
Kinds of segments
| Segment | Folder | Matches | params |
|---|---|---|---|
| static | blog |
/blog |
— |
| dynamic | [slug] |
/blog/hello |
{ slug: 'hello' } |
| catch-all | [...slug] |
/docs/a/b/c |
{ slug: ['a', 'b', 'c'] } |
| optional catch-all | [[...slug]] |
/docs and /docs/a/b |
{ slug: undefined } or an array |
| group | (name) |
doesn't appear in the URL | — |
| private | _name |
excluded from routing | — |
params is a Promise
In Next 16, params and searchParams are Promises — you wait for them with await:
export default async function Page({ params }: PageProps<'/blog/[slug]'>) {
const { slug } = await params
return <h1>{slug}</h1>
}PageProps<'/blog/[slug]'> is generated automatically by Next from the folder structure — the types are always correct.
generateStaticParams
For dynamic routes, you tell Next at build time which values exist, so it can pre-generate them as static pages:
export async function generateStaticParams() {
const posts = await getPosts()
return posts.map(post => ({ slug: post.slug }))
}This app does exactly that for every lesson (app/[locale]/[topic]/[lesson]/page.tsx).
Summary
- Next = React + routing + server rendering + a backend + optimizations.
- The folders in
app/are the URLs;page.tsxmakes the route public. [slug]is dynamic,(group)is invisible in the URL;paramsis awaited.