Lesson 10 of 2224 min read

Static Site Generation (SSG) in Next.js: Complete Guide

A complete guide to Static Site Generation in Next.js, covering generateStaticParams and how build-time rendering works under the hood.

Author: CodersNexus

Static Site Generation (SSG) in Next.js: Complete Guide

Of the three rendering strategies introduced back in Lesson 1.1 — SSR, CSR, and SSG — Static Site Generation is often the fastest and cheapest to run in production, because the work of building a page's HTML happens exactly once, ahead of time, rather than repeatedly for every visitor. Once built, static pages can be served directly from a CDN, located physically close to each visitor, without any server computation per request.

This lesson goes deep into how SSG actually works in the App Router: which components render statically by default, how generateStaticParams pre-renders dynamic routes like blog posts or product pages at build time, and the tradeoffs you accept in exchange for that speed — namely, that static content doesn't automatically reflect changes made after the build finishes (a limitation the next lesson's topic, ISR, directly addresses).

Learning Objectives

  • Explain how Static Site Generation works in the Next.js App Router.
  • Understand which pages are statically generated by default.
  • Use generateStaticParams to pre-render dynamic routes at build time.
  • Identify the tradeoffs of SSG compared to SSR.
  • Recognize real-world content types best suited to static generation.

Core Definitions

  • Static Site Generation (SSG): A rendering strategy where a page's HTML is generated once, at build time, and reused for every subsequent visitor until the next build.
  • Build time: The point at which running `next build` compiles and pre-renders your application, before it's deployed.
  • generateStaticParams: A function exported from a dynamic route file that returns a list of parameter values Next.js should pre-render as static pages at build time.
  • Static export: A fully static build output (via `next export` behavior or output: 'export' config) consisting entirely of static HTML/JS/CSS files with no server required at runtime.
  • CDN (Content Delivery Network): A globally distributed network of servers that caches and serves static files from a location physically close to each visitor.

Detailed Explanation

By default, a page in the App Router that doesn't use any dynamic, per-request data (like cookies, headers, or search params) and doesn't opt out explicitly, is statically rendered at build time. When you run `next build`, Next.js executes each eligible page's rendering logic once, produces the resulting HTML, and stores it as a static asset ready to be served instantly to every visitor — no server computation happens again until the next deployment.

This works cleanly for a page with fixed content, like an About page. But what about a blog with a page.tsx at app/blog/[slug]/page.tsx — a dynamic route that could correspond to hundreds of different posts? By default, dynamic routes without further configuration are rendered on-demand (effectively behaving like SSR) because Next.js doesn't know in advance which slug values exist.

This is exactly what generateStaticParams solves. By exporting a generateStaticParams function alongside your dynamic page component, you tell Next.js precisely which parameter values to pre-render as static HTML during the build. This function typically fetches a list of known values — say, every blog post's slug from a CMS or database — and returns them as an array of objects. Next.js then runs the page's rendering logic once per returned value, generating a complete, separate static HTML file for each post, all before the site is ever deployed.

The tradeoff is freshness. Because SSG content is generated once at build time, if the underlying data changes afterward — a blog post gets edited, a price updates — visitors will keep seeing the old static version until you trigger a new build and deployment. For content that changes constantly, this staleness is unacceptable, and SSR (or the middle-ground approach of Incremental Static Regeneration, covered next) becomes more appropriate. But for content that changes infrequently — marketing pages, documentation, most blog posts once published — SSG's speed and cost advantages are hard to beat: no server compute per request, trivially cacheable at the CDN edge, and extremely resilient to traffic spikes since there's no per-request rendering work to bottleneck.

Diagram Description

Visualize the SSG build-time pipeline:

[Run `next build`] --> [Next.js finds app/blog/[slug]/page.tsx] --> [Calls generateStaticParams()] --> [Returns: [{slug:'post-1'}, {slug:'post-2'}, {slug:'post-3'}]]
--> [Renders page.tsx once per slug] --> [Produces 3 static HTML files: /blog/post-1, /blog/post-2, /blog/post-3]
--> [Deploy to CDN] --> [Every visitor served instantly from cache, no server work per request]

Comparison Table

AspectStatic Site Generation (SSG)Server-Side Rendering (SSR)
When HTML is builtOnce, at build timeOn every request
Server compute per visitNone (served from cache/CDN)Required on every request
Content freshnessFixed until next build/deployAlways up to date
Best forBlogs, docs, marketing pages, product catalogs updated occasionallyPersonalized, frequently changing, or per-user content
Scaling under high trafficExtremely cheap (CDN-served)More server resources required as traffic grows

Next.js Practical Example

// app/blog/[slug]/page.tsx — statically generated dynamic route

async function getAllPosts() {
  const res = await fetch('https://api.example.com/posts');
  return res.json();
}

async function getPostBySlug(slug: string) {
  const res = await fetch(`https://api.example.com/posts/${slug}`);
  return res.json();
}

// Tells Next.js exactly which slugs to pre-render at build time
export async function generateStaticParams() {
  const posts = await getAllPosts();
  return posts.map((post) => ({ slug: post.slug }));
}

export default async function BlogPostPage({
  params,
}: {
  params: Promise<{ slug: string }>;
}) {
  const { slug } = await params;
  const post = await getPostBySlug(slug);

  return (
    <article>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </article>
  );
}

During `next build`, Next.js first calls generateStaticParams, which fetches the full list of blog posts and returns their slugs as an array of parameter objects. For each returned slug, Next.js then runs BlogPostPage's rendering logic exactly once, fetching that specific post's data and producing a fully static HTML file. If your blog has 200 posts, this process runs 200 times at build time, producing 200 separate static HTML files — none of which require any server computation again until the next deployment. Any slug not included in generateStaticParams's returned list would, by default, be handled dynamically on first request rather than failing outright, though this fallback behavior can be configured.

Industry Examples

  • Marketing agencies build entirely static client websites — homepage, about, services, contact — using SSG, since content rarely changes and static hosting is extremely cost-effective.
  • Documentation sites for open-source libraries pre-render every documentation page as static HTML using generateStaticParams, giving near-instant load times for developers browsing docs.
  • E-commerce catalogs pre-render product pages for their most popular or evergreen items via SSG, combining it with ISR (next lesson) for less-trafficked or frequently-updated items.
  • News outlets statically generate older, no-longer-changing articles for archival browsing, while newer breaking-news articles use SSR or ISR for up-to-the-minute freshness.
  • Company blogs and knowledge bases use SSG so that once an article is published and the site rebuilt, it can be served globally from a CDN with essentially zero ongoing server cost.

Interview Questions and Answers

Q1. What is Static Site Generation and when does the HTML get built?

Static Site Generation (SSG) is a rendering strategy where a page's HTML is generated once, at build time when `next build` runs, rather than per request. The resulting static file is then reused for every visitor until the site is rebuilt and redeployed.

Q2. How does Next.js pre-render dynamic routes statically?

By exporting a generateStaticParams function from a dynamic route's page file, which returns a list of parameter values (e.g., blog post slugs). Next.js calls this function at build time and renders the page once for each returned value, producing a separate static HTML file per value.

Q3. What happens to a dynamic route's parameter value that isn't included in generateStaticParams's returned list?

By default, Next.js can still render that value on-demand when first requested rather than returning an error, effectively falling back to dynamic, per-request rendering for values not known at build time; this fallback behavior can be further configured.

Q4. What is the main tradeoff of using SSG for frequently changing content?

SSG content is fixed at build time; if the underlying data changes afterward, visitors continue seeing the stale static version until a new build and deployment occur. This makes plain SSG unsuitable for content that needs to reflect changes immediately.

Q5. Why is SSG considered cheaper to run at scale than SSR?

Because SSG pages are pre-built once and served as static files, typically from a CDN, there's no server computation required per visitor request, unlike SSR which re-renders HTML on every request, consuming server resources proportional to traffic.

MCQs With Answers

1. When is a statically generated page's HTML built?

  1. On every request
  2. Once, at build time
  3. Only when a user clicks a button
  4. Never — it's built in the browser

Answer: B. Once, at build time

Explanation: SSG pages are pre-rendered once during the build process (`next build`) and reused for every subsequent visitor without rebuilding per request.

2. What is the purpose of generateStaticParams?

  1. To validate a form
  2. To tell Next.js which dynamic route values to pre-render at build time
  3. To fetch data on every request
  4. To style a component

Answer: B. To tell Next.js which dynamic route values to pre-render at build time

Explanation: generateStaticParams returns a list of parameter values so Next.js can generate a separate static page for each one during the build.

3. What is a key limitation of plain SSG?

  1. It cannot handle dynamic routes at all
  2. Content becomes stale until the next build and deployment
  3. It requires a database
  4. It can't be cached by a CDN

Answer: B. Content becomes stale until the next build and deployment

Explanation: Because SSG pages are built once, any underlying data changes afterward won't appear to visitors until the site is rebuilt and redeployed.

4. Why can SSG pages be served extremely cheaply at scale?

  1. They require a powerful server for every request
  2. They can be served as static files from a CDN with no per-request server computation
  3. They automatically compress all images
  4. They don't require a build step

Answer: B. They can be served as static files from a CDN with no per-request server computation

Explanation: Since the HTML is already generated, static pages can be served directly from a CDN without any server-side rendering work per visitor.

5. Which type of content is generally the best fit for SSG?

  1. A real-time stock ticker
  2. A personalized user dashboard
  3. A blog post that rarely changes after publishing
  4. A live chat interface

Answer: C. A blog post that rarely changes after publishing

Explanation: SSG suits content that is the same for every visitor and doesn't change frequently, since it's pre-built once and reused until the next deployment.

Common Mistakes to Avoid

  • Assuming every dynamic route is automatically statically generated without needing generateStaticParams.
  • Using SSG for highly personalized or rapidly changing content, resulting in visitors seeing stale data.
  • Forgetting that data changes after a build require a new deployment for static pages to reflect them, without also adopting ISR.
  • Trying to generateStaticParams for an unrealistically large dataset (millions of pages), causing impractically long build times.
  • Confusing 'static' with 'unchangeable forever' — static pages can absolutely be updated, just only via a new build/deploy, not instantly.

Interview Notes

  • SSG builds a page's HTML once at build time, reused for every visitor until the next deployment.
  • generateStaticParams pre-renders dynamic route values as separate static HTML files during the build.
  • Values not returned by generateStaticParams can still be handled dynamically on first request by default.
  • SSG's main tradeoff is data freshness — content is fixed until a new build and deploy occur.
  • SSG is ideal for content that changes infrequently: marketing pages, documentation, evergreen blog posts.

Key Takeaways

  • Static Site Generation delivers some of the fastest, cheapest-to-scale pages possible, since the rendering work happens once, not per request.
  • generateStaticParams is the mechanism that extends SSG's benefits to dynamic routes with many possible values, like blog posts or products.
  • The core tradeoff of SSG is freshness versus speed — a tradeoff every team must consciously evaluate per page or route.
  • Understanding SSG's limitations sets up the next lesson's topic, Incremental Static Regeneration, which addresses the staleness problem directly.

Summary

Static Site Generation pre-renders a page's HTML exactly once, at build time, producing a static file that can be served instantly to every visitor from a CDN without any per-request server computation. For dynamic routes with many possible values, such as blog posts or products, the generateStaticParams function tells Next.js exactly which values to pre-render as individual static pages during the build. This approach delivers exceptional speed and scalability at low cost, but comes with a clear tradeoff: content is fixed until the next build and deployment, making plain SSG unsuitable for frequently changing or highly personalized data. SSG is best suited to content that changes infrequently — marketing pages, documentation, and most published blog content.

Frequently Asked Questions

Static Site Generation means building a page's HTML once, ahead of time (during the build process), rather than generating it fresh for every visitor. The same pre-built HTML file is then served to everyone until the site is rebuilt.

SSG builds HTML once at build time and reuses it for all visitors. SSR builds HTML fresh on the server for every single request, ensuring up-to-date content at the cost of server computation per visit.

It returns an array of objects, where each object's keys match the dynamic segment names in the route's folder (e.g., { slug: 'my-post' } for a [slug] folder), telling Next.js exactly which values to pre-render as static pages.

The dynamic route will typically be rendered on-demand per request rather than pre-built at compile time, behaving more like server-side rendering for that route unless you explicitly configure static generation via generateStaticParams.

Only by rebuilding and redeploying the site (or by adopting Incremental Static Regeneration, covered in the next lesson, which allows automatic background regeneration without a full manual redeploy).

Generally no. SSG produces the same HTML for every visitor, which doesn't work for content unique to each individual user. SSR or client-side data fetching is typically more appropriate for personalized content.

Yes, extremely well — since the output is a static HTML file that doesn't change per visitor, it can be cached and served from CDN edge locations physically close to each user, resulting in very fast load times globally.

Yes. Rendering strategy can be chosen per route in Next.js, so you might use SSG for your marketing pages and blog, while using SSR for a dashboard or account settings page within the same application.

Build time increases with the number of pages generateStaticParams produces, since each one is individually rendered during the build. Extremely large datasets (hundreds of thousands or millions of pages) can make full static generation impractical, favoring ISR or on-demand rendering instead.

They're related but not identical. SSG refers to the build-time rendering strategy for individual pages within a Next.js app (which may still use a Node.js server for other dynamic routes). A full static export (via output: 'export') produces an entire site of only static files with no server required at all, which requires every route in the app to be compatible with static rendering.