Skip to content

Static Site Generation (SSG)

Static Site Generation (SSG) is the term for pre-rendering pages into static HTML files at build time, ready to be served instantly from a CDN. This lesson connects the term to what you've already learned as "static rendering" in the App Router.

SSG Is What Static Rendering Produces

"Static Site Generation" and "static rendering" describe the same underlying behavior, viewed from slightly different angles: SSG emphasizes the output (a fully static site, or fully static routes within a larger app), while "static rendering" emphasizes the App Router's process of deciding, per route, whether to render statically.

In the Pages Router, SSG was explicit: you exported a getStaticProps function, and optionally getStaticPaths for dynamic routes. In the App Router, it's implicit: any route without request-specific data automatically qualifies, and generateStaticParams replaces getStaticPaths for dynamic segments.

// App Router SSG-style route
export async function generateStaticParams() {
  const posts = await getAllPostSlugs();
  return posts.map((slug: string) => ({ slug }));
}

export default async function PostPage({ params }: { params: { slug: string } }) {
  const post = await getPostBySlug(params.slug);
  return <article>{post.title}</article>;
}

Every slug returned by generateStaticParams becomes its own pre-rendered static HTML file at build time.

SSG: App Router vs. Pages Router

// App Router
export async function generateStaticParams() { /* ... */ }

// Pages Router
export async function getStaticPaths() { /* ... */ }
export async function getStaticProps() { /* ... */ }
  • generateStaticParams (App Router) plays the role of getStaticPaths (Pages Router).
  • In the App Router, data fetching happens directly in the async page component, not in a separate getStaticProps.
  • Both approaches produce the same result: pre-rendered HTML files generated at build time.
  • A fully static site can be exported and hosted on any static file host, using output: "export" in next.config.js.

SSG Cheat Sheet

Key facts about how SSG behaves in Next.js.

Question Answer
When is HTML generated? At build time (next build)
What triggers SSG for a dynamic route? generateStaticParams
Can SSG pages still update later? Yes, if combined with ISR (revalidate)
Best hosting for pure SSG sites Any static host or CDN
Pages Router equivalent getStaticProps + getStaticPaths

Exporting a Fully Static Site

For sites with no server-rendered routes, API routes, or Server Actions, Next.js can export a completely static build — plain HTML, CSS, and JS files with no Node.js server required at runtime — using the output: "export" configuration option.

// next.config.js
module.exports = {
  output: "export",
};

// npm run build
// → outputs static files to the "out/" directory

This mode disables features that require a server at runtime, like Route Handlers with dynamic behavior, ISR revalidation, and Server Actions.

Ideal Use Cases for SSG

SSG shines for content that's the same for every visitor and doesn't need to update instantly — documentation sites, marketing pages, and blogs are the classic examples, especially when paired with ISR for periodic content refreshes without a full rebuild.

Common Mistakes

  • Trying to use Server Actions or dynamic Route Handlers in a project configured with output: "export".
  • Forgetting generateStaticParams when a dynamic route should be fully pre-rendered.
  • Assuming SSG content can never change — ISR (revalidate) allows periodic updates on top of SSG.
  • Using SSG for highly personalized content that's actually different for every visitor.

Key Takeaways

  • SSG is the output of static rendering: HTML generated once at build time.
  • generateStaticParams replaces the Pages Router's getStaticPaths for dynamic routes.
  • output: "export" produces a fully static site with no Node.js server required.
  • SSG pairs naturally with ISR for content that needs occasional updates.
  • SSG is ideal for content that's identical for every visitor: docs, marketing pages, blogs.

Pro Tip

Before configuring output: "export" for a fully static deployment, audit your app for any Server Actions, dynamic Route Handlers, or ISR usage — these features require a server at runtime and are incompatible with a pure static export.