Next.js cookbook · Intermediate

Pre-render dynamic pages with generateStaticParams and ISR

Serve thousands of blog/product pages as static HTML that refreshes periodically.

Approach

Export generateStaticParams to pre-render the most important paths at build time, allow other paths to render on demand (dynamicParams = true) and be cached, and set revalidate for periodic regeneration (ISR). Use on-demand revalidation when content changes.

Solution

// app/blog/[slug]/page.tsx
export const revalidate = 3600;          // regenerate at most hourly
export const dynamicParams = true;       // render unknown slugs on demand, then cache

export async function generateStaticParams() {
  const posts = await cms.listPosts({ limit: 200, sort: "-views" });   // prebuild the popular ones
  return posts.map((p) => ({ slug: p.slug }));
}

export default async function BlogPost({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params;
  const post = await cms.getPost(slug);
  if (!post) notFound();
  return (
    <article>
      <h1>{post.title}</h1>
      <div dangerouslySetInnerHTML={{ __html: post.sanitizedHtml }} />
    </article>
  );
}

// app/api/revalidate/route.ts — called by the CMS webhook
import { revalidatePath } from "next/cache";
export async function POST(request: Request) {
  if (request.headers.get("x-revalidate-secret") !== process.env.REVALIDATE_SECRET) return new Response(null, { status: 401 });
  const { slug } = await request.json();
  revalidatePath(`/blog/${slug}`);
  return Response.json({ revalidated: true });
}

Pitfalls

  • Pre-building every page (long builds) — prebuild the popular subset.
  • Using cookies/headers in the page, which forces dynamic rendering.
  • Rendering unsanitized CMS HTML.

Variations

  • Cache Components ('use cache' + cacheLife) in Next.js 16.
  • Fully static export (output: 'export') for sites without server features.

Further reading: Next.js: generateStaticParams

Reference: https://nextjs.org/docs/app/api-reference/functions/generate-static-params

More Next.js recipes