Dynamic Routes and generateStaticParams in Next.js
Dynamic routes let one file serve many URLs, such as every blog post or product. With generateStaticParams you can pre-render the popular ones at build time.
Segment types
[slug]- one segment:/blog/hello.[...slug]- catch-all:/docs/a/b/cgives['a','b','c'].[[...slug]]- optional catch-all: also matches/docs.
Pre-render at build time
// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
const posts = await getAllPosts();
return posts.map((post) => ({ slug: post.slug }));
}
export default async function Post({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const post = await getPost(slug);
if (!post) notFound();
return <Article post={post} />;
}
Pages not returned by generateStaticParams
By default, other slugs are rendered on first request and then cached. To return a 404 for anything not pre-generated, export:
export const dynamicParams = false;
Large sites
Building 100,000 pages at deploy time is slow. Pre-render only the most visited pages and let the rest render on demand:
export async function generateStaticParams() {
const top = await db.post.findMany({ orderBy: { views: 'desc' }, take: 500, select: { slug: true } });
return top;
}
Nested dynamic segments
// app/shop/[category]/[product]/page.tsx
export async function generateStaticParams() {
const products = await getProducts();
return products.map((p) => ({ category: p.categorySlug, product: p.slug }));
}
Remember to call notFound() for unknown slugs so search engines get a real 404 instead of an empty page.
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.