Dynamic routes and dynamic segments in Next.js
What are Dynamic Routes?
Dynamic routes allow you to create pages that match variable URL segments. Instead of creating a file for every possible path, you use bracket notation to define dynamic parameters.
Basic Dynamic Segments
app/
blog/
[slug]/
page.tsx → /blog/hello-world, /blog/my-post
users/
[id]/
page.tsx → /users/1, /users/abctsx
// app/blog/[slug]/page.tsx
export default async function BlogPost({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const post = await getPost(slug);
return (
<article>
<h1>{post.title}</h1>
<div>{post.content}</div>
</article>
);
}Catch-All Segments
Match multiple path segments with [...param]:
app/
docs/
[...slug]/
page.tsx → /docs/a, /docs/a/b, /docs/a/b/ctsx
// app/docs/[...slug]/page.tsx
export default async function Docs({
params,
}: {
params: Promise<{ slug: string[] }>;
}) {
const { slug } = await params;
// /docs/react/hooks → slug = ["react", "hooks"]
return <div>Path: {slug.join("/")}</div>;
}Optional Catch-All Segments
Match the path with or without segments using [[...param]]:
app/
shop/
[[...categories]]/
page.tsx → /shop, /shop/clothes, /shop/clothes/shirtstsx
// app/shop/[[...categories]]/page.tsx
export default async function Shop({
params,
}: {
params: Promise<{ categories?: string[] }>;
}) {
const { categories } = await params;
// /shop → categories = undefined
// /shop/clothes → categories = ["clothes"]
// /shop/clothes/men → categories = ["clothes", "men"]
return <ProductGrid categories={categories} />;
}generateStaticParams
Pre-render dynamic routes at build time:
tsx
// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
const posts = await getAllPosts();
return posts.map((post) => ({
slug: post.slug,
}));
}
// Generates: /blog/post-1, /blog/post-2, etc. at build timeMultiple Dynamic Segments
app/
[locale]/
blog/
[slug]/
page.tsx → /en/blog/hello, /ua/blog/hellotsx
// app/[locale]/blog/[slug]/page.tsx
export default async function BlogPost({
params,
}: {
params: Promise<{ locale: string; slug: string }>;
}) {
const { locale, slug } = await params;
const post = await getPost(slug, locale);
return <article>{post.title}</article>;
}Summary
| Pattern | Example | Matches |
|---|---|---|
[slug] | /blog/[slug] | /blog/hello (one segment) |
[...slug] | /docs/[...slug] | /docs/a/b/c (one or more) |
[[...slug]] | /shop/[[...slug]] | /shop, /shop/a/b (zero or more) |
Important:
Dynamic routes are the foundation of Next.js routing. Use [param] for single segments, [...param] for catch-all, and [[...param]] for optional catch-all. Combine with generateStaticParams for static generation of dynamic pages.
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.