How Static Site Generation (SSG) Works in Next.js
SSG (Static Site Generation) is a rendering strategy where HTML pages are generated once at build time (next build). After deployment these pages are served as regular static files via CDN.
How It Works
Build (next build)
Next.js calls the server component or getStaticProps, runs all API/DB requests and generates HTML files for each page.
Deploy
The ready HTML files are placed on a CDN. The server no longer participates in page generation.
User request
When a user opens a page, the CDN instantly serves the ready HTML. No waiting for the server, no real-time rendering.
SSG in App Router
In the App Router (Next.js 13+) SSG is the default behavior. If a component does not use dynamic data, Next.js will automatically generate it statically:
// app/docs/page.tsx
// This page will be statically generated at build time
export default async function DocsPage() {
const res = await fetch('https://api.hackfrontend.com/docs')
const docs = await res.json()
return (
<ul>
{docs.map((doc: { slug: string; title: string }) => (
<li key={doc.slug}>{doc.title}</li>
))}
</ul>
)
}
By default fetch in server components caches the result. This is the equivalent of SSG: the request runs once at build time.
Dynamic Routes
For dynamic pages you need to specify which paths to generate in advance. Use generateStaticParams for this:
// app/docs/[slug]/page.tsx
export async function generateStaticParams() {
const res = await fetch('https://api.hackfrontend.com/docs')
const docs = await res.json()
return docs.map((doc: { slug: string }) => ({
slug: doc.slug
}))
}
export default async function DocPage({
params
}: {
params: { slug: string }
}) {
const res = await fetch(
`https://api.hackfrontend.com/docs/${params.slug}`
)
const doc = await res.json()
return (
<article>
<h1>{doc.title}</h1>
<div>{doc.content}</div>
</article>
)
}
At build time Next.js calls generateStaticParams, gets the list of slugs and generates a separate HTML file for each.
SSG in Pages Router (Legacy)
In the Pages Router SSG uses getStaticProps:
// pages/docs/index.tsx
export async function getStaticProps() {
const res = await fetch('https://api.hackfrontend.com/docs')
const docs = await res.json()
return {
props: { docs }
}
}
export default function DocsPage({ docs }) {
return (
<ul>
{docs.map(doc => (
<li key={doc.slug}>{doc.title}</li>
))}
</ul>
)
}
For dynamic routes getStaticPaths is also needed:
// pages/docs/[slug].tsx
export async function getStaticPaths() {
const res = await fetch('https://api.hackfrontend.com/docs')
const docs = await res.json()
return {
paths: docs.map(doc => ({ params: { slug: doc.slug } })),
fallback: false
}
}
export async function getStaticProps({ params }) {
const res = await fetch(
`https://api.hackfrontend.com/docs/${params.slug}`
)
const doc = await res.json()
return { props: { doc } }
}
When to Use SSG
Good for:
- Documentation (like on Hack Frontend)
- Blogs and articles
- Landing pages, marketing sites
- FAQ, reference sections
- Product catalogs that update infrequently
Not suitable for:
- Pages with personalized content (profile, dashboard)
- Data that changes every second (stock prices, chats)
- Pages that depend on cookies or request headers
Interview tip:
A common question: "What if the data becomes stale after the build?". Answer: that is what ISR (Incremental Static Regeneration) is for. It lets you update static pages without a full rebuild.
Benefits of SSG
- Speed. Ready HTML is served instantly. No server wait time.
- SEO. Search bots get the full HTML content right away.
- Reliability. Static files do not depend on database or API availability at request time.
- Cost. CDN hosting is cheaper than server-side rendering on every request.
Useful Resources
- nextjs.org/docs — static rendering documentation
- generateStaticParams — API Reference