`generateStaticParams` Explained with Real Examples

generateStaticParams tells Next.js which values of a dynamic segment to prerender at build time instead of on demand. Learn its signature and return shape.

7 min read

The next.js generateStaticParams function tells Next.js which values of a dynamic route segment to render ahead of time at build, instead of rendering them the first time a visitor requests that URL. Export it alongside a page that uses a dynamic segment.

App.tsxApp.tsx
// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
  const posts = await fetch("https://api.example.com/posts").then((res) =>
    res.json()
  );
  return posts.map((post: { slug: string }) => ({ slug: post.slug }));
}

Each object in the returned array becomes one page built at compile time. Returning ten post slugs here builds ten static blog post pages before the app ever receives a real visitor.

The return shape

The function must return an array of objects, and each object's keys must match the dynamic segment names in the route's file path exactly.

RouteReturn type
app/product/[id]/page.tsx{ id: string }[]
app/products/[category]/[product]/page.tsx{ category: string; product: string }[]
app/product/[...slug]/page.tsx{ slug: string[] }[]

A single dynamic segment needs one key per object; a catch-all segment needs an array of strings as its value, matching the same shape the page's own params prop expects.

Multiple dynamic segments

For a route with more than one dynamic segment, a single function at the page level can generate every value at once.

App.tsxApp.tsx
// app/products/[category]/[product]/page.tsx
export async function generateStaticParams() {
  const products = await fetch("https://api.example.com/products").then(
    (res) => res.json()
  );
  return products.map((p: { category: string; id: string }) => ({
    category: p.category,
    product: p.id,
  }));
}

A layout above the page can only generate the segments up to its own level, since it has no visibility into segments defined deeper in the tree. A nested version of this function in a child segment also receives the parent's resolved value as an argument, which is useful for fetching only the products inside one already-known category rather than refetching the full catalog at every level.

This bottom-up approach, generating every segment from the deepest page, is usually the simpler starting point. Reach for the parent-to-child version only once a route genuinely benefits from splitting one large fetch into smaller, scoped ones per level.

What happens to unlisted values

By default, a value this function does not return still renders normally the first time someone requests it, rather than failing. Setting dynamicParams to false in the same file changes that: any value outside the returned list then 404s instead of rendering on demand.

typescripttypescript
// app/blog/[slug]/page.tsx
export const dynamicParams = false;

This option belongs to the caching model that predates Cache Components, so confirm which model a project uses before relying on it, since Cache Components changes how dynamic segments without a static value are validated at build time.

Common mistake

Returning an empty array by mistake, rather than omitting the function entirely, quietly disables build-time prerendering for that route instead of causing an error. An empty array is actually a valid way to defer every value to request time, so it fails silently rather than loudly, which makes it easy to miss during a code review.

For how these values reach the page itself, see page.js props, params, and search params. For the underlying dynamic segment convention this function fills in, see dynamic routes in Next.js.

Rune AI

Rune AI

Key Insights

  • generateStaticParams returns an array of objects, one per route to prerender.
  • Each object's keys must match the dynamic segment names in the file path.
  • Values it does not return still render on request unless dynamicParams is false.
  • A child segment's function receives the parent's resolved params as an argument.
  • fetch calls inside it are deduplicated against the same requests in the page itself.
RunePowered by Rune AI

Frequently Asked Questions

What happens to a value not returned by generateStaticParams?

By default, Next.js still renders it, just at request time on first visit instead of ahead of time at build. Setting dynamicParams to false instead makes any unlisted value 404.

Can generateStaticParams run in a layout instead of a page?

Yes, but a layout can only generate params for the dynamic segments up to its own level. A page can generate params for every dynamic segment in its full path, including ones above it.

Does generateStaticParams work with route handlers?

Yes. Exporting it from a route.ts file statically generates that API response at build time for each returned value, the same way it works for a page.

Conclusion

generateStaticParams returns the list of dynamic segment values Next.js should prerender at build time. Values outside that list still render normally on first request unless dynamicParams is turned off.