Static Generation (SSG)
Static Generation pre-renders pages at build time. The HTML is generated once and reused for every request.
When Pages Are Static
Pages are static by default when they:
- Don't use dynamic functions (
cookies(),headers()) - Don't use
searchParams - Fetch data without
cache: 'no-store'
// This page is statically generated
export default async function AboutPage() {
const team = await fetch('https://api.example.com/team')
.then(res => res.json())
return (
<div>
<h1>Our Team</h1>
{team.map(member => (
<div key={member.id}>{member.name}</div>
))}
</div>
)
}
Static Dynamic Routes
For dynamic routes, use generateStaticParams:
// app/blog/[slug]/page.tsx
// Tell Next.js which pages to generate
export async function generateStaticParams() {
const posts = await fetch('https://api.example.com/posts')
.then(res => res.json())
return posts.map((post) => ({
slug: post.slug,
}))
}
// This runs at build time for each slug
export default async function BlogPost({
params,
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params
const post = await fetch(`https://api.example.com/posts/${slug}`)
.then(res => res.json())
return <article>{post.content}</article>
}
Handling Missing Pages
Control behavior for paths not returned by generateStaticParams:
// Generate only specified paths, 404 for others
export const dynamicParams = false
// Generate on-demand for new paths (default)
export const dynamicParams = true
With dynamicParams = true, new paths are generated on first request and cached.
Build Output
During build, Next.js shows which pages are static:
Route (app) Size First Load JS
┌ ○ / 5.2 kB 89.1 kB
├ ○ /about 2.1 kB 86.0 kB
├ ● /blog/[slug] 3.4 kB 87.3 kB
│ ├ /blog/hello-world
│ ├ /blog/nextjs-guide
│ └ /blog/react-tips
└ λ /dashboard 4.8 kB 88.7 kB
○ (Static) prerendered as static content
● (SSG) prerendered as static HTML (uses generateStaticParams)
λ (Dynamic) server-rendered on demand
Benefits of Static Generation
- Speed: Pre-built HTML served from CDN
- Cost: No server compute per request
- Reliability: No runtime errors from data fetching
- SEO: Full HTML available immediately
When to Use SSG
| Good for SSG | Not good for SSG |
|---|---|
| Marketing pages | User dashboards |
| Blog posts | Real-time data |
| Documentation | Personalized content |
| Product listings | Search results |
Summary
- Pages without dynamic functions are static by default
- Use
generateStaticParamsfor dynamic routes - Static pages are built once and cached on CDN
- Check build output to verify rendering strategy
- Best for content that doesn't change per-user or frequently

