All Posts
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.

Links / Resources

Quotes #

You have the right to work, but for the work's sake only. You have no right to the fruits of work.

— Bhagavad Gita