Why this matters
The production reason.
Dynamic routes are flexible, but if every slug waits for a server request before rendering, your first byte gets slower and crawlers see less stable output.
Use generateStaticParams when you already know the important slugs at build time: blog posts, product pages, docs, landing pages, and category archives.
Keep this paired with a sensible fallback strategy for content that changes often, so new pages can still appear without a full rebuild when your app needs that behavior.
// app/blog/[slug]/page.jsx
export async function generateStaticParams() {
const posts = await getPosts();
return posts.map((post) => ({
slug: post.slug,
}));
}
export default async function BlogPost({ params }) {
const post = await getPostBySlug(params.slug);
return <Article post={post} />;
}