Next.jsRoutingTypeScript
Understanding Dynamic Routes and Slugs in Next.js
How Next.js App Router handles dynamic segments, catch-all routes, and optional catch-all routes with practical examples.
10 November 20257 min read
Next.js App Router uses folder names wrapped in square brackets to create dynamic URL segments. This post covers [slug], [...rest], and [[...rest]] with practical examples from real projects.
1. Single Dynamic Segment — [slug]
A folder named [slug] matches any single path segment. The value is accessible via params.slug in Server Components.
// app/blog/[slug]/page.tsx
export default async function BlogPage({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
return <h1>{slug}</h1>;
}2. Catch-All Routes — [...rest]
Prefix with ... to match multiple segments: /docs/a/b/c → params.rest = ["a", "b", "c"].
// app/docs/[...rest]/page.tsx
export default async function DocsPage({
params,
}: {
params: Promise<{ rest: string[] }>;
}) {
const { rest } = await params;
return <p>Segments: {rest.join(" / ")}</p>;
}3. Optional Catch-All — [[...rest]]
Double brackets make the segment optional — the route also matches the root path /docs where params.rest is undefined.