Next.js SSG — Static Site Generation with Next.js Explained
In this tutorial, you will learn about Next.js SSG. We cover key concepts, practical examples, and best practices to help you master this topic.
Next.js SSG pre-builds pages at compile time using getStaticProps and getStaticPaths, generating static HTML that loads instantly from CDN edge.
What You'll Learn
By the end of this tutorial, you'll understand how to configure Next.js for static generation, use getStaticProps and getStaticPaths, optimize builds, and deploy Next.js SSG sites.
Why It Matters
Next.js makes SSG practical for real-world applications by handling routing, data fetching, image optimization, and build optimization out of the box. It's the most popular framework for static site generation in the React ecosystem.
Real-World Use
A documentation site built with Next.js SSG generates hundreds of doc pages at build time from markdown files. Each page is pre-rendered, optimized, and deployed to Vercel's edge network. Users get instant page loads while the team writes content in markdown.
Next.js SSG Architecture
graph TD
A[Next.js SSG App] --> B[Build Process
next build]
B --> C{Page Type?}
C -->|Static| D[getStaticProps]
C -->|Dynamic| E[getStaticPaths +
getStaticProps]
C -->|Client| F[Client-side fetch]
D --> G[Pre-rendered HTML]
E --> G
F --> H[Runtime rendering]
G --> I[Static Export
or CDN Deploy]
H --> J[Browser]
I --> J
style D fill:#27ae60,color:#fff
style E fill:#3498db,color:#fff
style G fill:#e67e22,color:#fff
Setting Up Next.js SSG
// pages/index.js — Static homepage
export default function Home({ posts, buildTime }) {
return (
<div>
<h1>My SSG Blog</h1>
<p>Built at: {new Date(buildTime).toLocaleString()}</p>
<ul>
{posts.map(post => (
<li key={post.id}>
<a href={`/posts/${post.slug}`}>{post.title}</a>
</li>
))}
</ul>
</div>
);
}
// getStaticProps runs at build time
export async function getStaticProps() {
const res = await fetch('https://jsonplaceholder.typicode.com/posts');
const posts = await res.json();
return {
props: {
posts: posts.slice(0, 10),
buildTime: Date.now()
}
};
}
Dynamic Routes with SSG
// pages/posts/[slug].js — Dynamic SSG page
export default function Post({ post, buildTime }) {
return (
<article>
<h1>{post.title}</h1>
<p className="meta">
Built at: {new Date(buildTime).toISOString()}
</p>
<div>{post.body}</div>
</article>
);
}
// getStaticPaths: define which slugs to pre-build
export async function getStaticPaths() {
const res = await fetch('https://jsonplaceholder.typicode.com/posts');
const posts = await res.json();
const paths = posts.slice(0, 10).map(post => ({
params: { slug: post.slug || String(post.id) }
}));
return { paths, fallback: false };
}
// getStaticProps: fetch data for each slug
export async function getStaticProps({ params }) {
const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.slug}`);
const post = await res.json();
return {
props: {
post,
buildTime: Date.now()
}
};
}
Static Export Configuration
// next.config.js — Full static export
module.exports = {
output: 'export', // Generates static HTML
// Optional: Configure image optimization
images: {
unoptimized: true // Required for static export
},
// Optional: Set base path for subdirectory deployment
basePath: '/docs',
// Optional: Internationalization
i18n: {
locales: ['en', 'fr', 'es'],
defaultLocale: 'en',
},
};
// Build command: next build && next export
// Output goes to "out/" directory by default
// Package.json scripts
{
"scripts": {
"dev": "next dev",
"build": "next build",
"export": "next export",
"deploy": "next build && next export && npx netlify-cli deploy --dir=out"
}
}
Common Mistakes
- Using getServerSideProps when getStaticProps works. If your data doesn't change per request, use getStaticProps. It's faster and cheaper.
- Not using fallback for dynamic routes. Without fallback, missing routes return 404. Use
fallback: trueorfallback: 'blocking'for uncached pages. - Forgetting to configure output: export. Without
output: 'export', Next.js generates a hybrid app that needs a Node.js server. - Over-fetching data in getStaticPaths. Generating thousands of paths at once slows builds. Batch paths or use fallback for large sites.
- Storing secrets in getStaticProps. Build-time code can be exposed. Use environment variables and server-only imports for API keys.
Practice Questions
- What functions does Next.js provide for SSG data fetching?
- How do you configure Next.js to output fully static files?
- What does the
fallbackoption do in getStaticPaths? - How does getStaticPaths know which pages to pre-build?
- Can you use client-side data fetching alongside SSG in Next.js?
Challenge: Build a Next.js SSG blog with at least 10 posts from an external API, dynamic routes for individual posts, a static homepage listing all posts, and configure it for full static export.
FAQ
Mini Project
Create a Next.js SSG portfolio site: build a homepage with static content, projects page that fetches data from an API at build time, individual project pages with dynamic routes, a contact page with static content, and configure it for full static export.
What's Next
Now you can build Next.js SSG pages. Dive deeper into getStaticProps to master build-time data fetching strategies.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro