100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
JavaScript

Static Site Generation

Learn how Next.js pre-renders pages to static HTML at build time using Static Site Generation, and when it's the right rendering strategy.

Rendering ModelsBeginner8 min readJul 10, 2026
Analogies

What Static Site Generation Means

Static Site Generation (SSG) means Next.js renders a page's HTML once, at build time, rather than on every incoming request. The resulting HTML, along with a JSON payload of the page's data, is written to disk and can then be served instantly from a CDN edge node for every visitor, with no server compute needed per request. In the App Router, a page becomes statically generated by default when it has no dynamic functions like cookies() or headers() and its data fetches don't opt out of caching.

🏏

Cricket analogy: It's like printing the full scorecard and match report the morning after a Test match ends -- once printed, every reader gets the identical page instantly, instead of a clerk recalculating the scorecard from raw ball-by-ball data for each reader.

Fetching Data at Build Time

Inside an App Router Server Component, a plain fetch() call is cached by default, which is what makes the page eligible for static generation -- Next.js runs the fetch once during the build, stores the result, and reuses that HTML for every subsequent request until a redeploy or explicit revalidation happens. For dynamic route segments like blog posts, generateStaticParams() tells Next.js which specific paths (e.g. every slug) to pre-render at build time, so a request for /blog/hello-world is served from a pre-built file rather than triggering fresh computation.

🏏

Cricket analogy: generateStaticParams is like a broadcaster deciding in advance which specific matches of the season to produce highlight reels for, rather than generating a highlight package on demand every time someone asks for one.

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

async function getPost(slug: string) {
  // Cached fetch -> eligible for static generation
  const res = await fetch(`https://api.example.com/posts/${slug}`);
  if (!res.ok) throw new Error('Failed to fetch post');
  return res.json();
}

export default async function BlogPostPage({ params }: { params: { slug: string } }) {
  const post = await getPost(params.slug);
  return (
    <article>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </article>
  );
}

Pages built with SSG can be served from a CDN edge cache with zero server compute per request, giving the lowest possible Time to First Byte. This makes SSG the best default choice for marketing pages, documentation, and blog posts where content doesn't change on every request.

SSG vs Dynamic Rendering

A page opts out of static generation the moment it reads request-specific data such as cookies(), headers(), searchParams in a way that affects output, or calls fetch with { cache: 'no-store' }; Next.js then falls back to dynamic (per-request) rendering for that route. Choosing SSG only makes sense when the same HTML can be reused across many visitors -- a personalized dashboard showing a logged-in user's name is a poor SSG candidate, while a public product listing page is an excellent one.

🏏

Cricket analogy: It's like the difference between a pre-printed tournament schedule (same for everyone, good for SSG) and a personalized fantasy-league scorecard showing your specific team's points (different per user, needs dynamic rendering).

Statically generated pages are 'frozen' at build time. If your data changes frequently and every visitor needs the very latest version, plain SSG without revalidation will serve stale content until the next deploy -- consider Incremental Static Regeneration or dynamic rendering instead.

  • SSG pre-renders pages to static HTML at build time, so they can be served from a CDN with no per-request server compute.
  • In the App Router, pages are statically generated by default when they don't use request-specific APIs like cookies() or headers().
  • generateStaticParams() tells Next.js which dynamic route params (e.g. blog slugs) to pre-render at build time.
  • A plain cached fetch() call inside a Server Component makes a page eligible for static generation.
  • Using cookies(), headers(), or { cache: 'no-store' } opts a route out of static generation into dynamic rendering.
  • SSG is ideal for content that's the same for every visitor, like marketing pages, docs, and blog posts.
  • Plain SSG content is frozen until the next build/deploy, so highly dynamic or personalized content needs a different strategy.

Practice what you learned

Was this page helpful?

Topics covered

#JavaScript#NextJsStudyNotes#WebDevelopment#StaticSiteGeneration#Static#Site#Generation#Means#StudyNotes#SkillVeris