Developing SSG (Static Site Generation) for a website
Static Site Generation — generating HTML files at build time, not on every request. The server delivers ready HTML directly from CDN without server-side rendering or databases in the critical path. Result: minimal TTFB, scaling without additional servers, maximum reliability.
SSG is suitable for content that updates rarely or on schedule: documentation, blogs, landing pages, marketing sites, portfolios, catalogs.
Tools and their applications
| Tool | Stack | When to use |
|---|---|---|
| Next.js (output: export) | React | Already using React/Next.js |
| Nuxt (nitro static) | Vue | Already using Vue/Nuxt |
| Astro | Any/None | Content site, minimal JS |
| SvelteKit (adapter-static) | Svelte | Svelte projects |
| Eleventy | No framework | Maximum template flexibility |
| Hugo | Go | Thousands of pages, build speed critical |
For most tasks we recommend Astro — it generates zero client-side JS by default and supports React/Vue/Svelte components simultaneously.
Implementation on Astro
---
// src/pages/blog/[slug].astro
import { getCollection, type CollectionEntry } from 'astro:content';
import BlogLayout from '@/layouts/BlogLayout.astro';
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map(post => ({
params: { slug: post.slug },
props: { post },
}));
}
interface Props { post: CollectionEntry<'blog'>; }
const { post } = Astro.props;
const { Content, headings, remarkPluginFrontmatter } = await post.render();
---
<BlogLayout
title={post.data.title}
description={post.data.description}
publishedAt={post.data.publishedAt}
readingTime={remarkPluginFrontmatter.minutesRead}
>
<Content />
</BlogLayout>
// src/content/config.ts — typed content schema
import { defineCollection, z } from 'astro:content';
const blog = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
description: z.string().max(160),
publishedAt: z.date(),
tags: z.array(z.string()),
draft: z.boolean().default(false),
}),
});
export const collections = { blog };
Integration with Headless CMS
Static sites don't mean static content. Data is fetched at build time from API:
// src/lib/cms.ts — Contentful integration
import contentful from 'contentful';
const client = contentful.createClient({
space: import.meta.env.CONTENTFUL_SPACE_ID,
accessToken: import.meta.env.CONTENTFUL_ACCESS_TOKEN,
});
export async function getProducts(): Promise<Product[]> {
const entries = await client.getEntries<ProductFields>({
content_type: 'product',
order: ['-sys.createdAt'],
limit: 1000,
});
return entries.items.map(item => ({
id: item.sys.id,
name: item.fields.name,
slug: item.fields.slug,
price: item.fields.price,
image: `https:${item.fields.image.fields.file.url}`,
}));
}
On each deploy (or via CMS webhook) the site rebuilds with fresh data.
Image optimization
---
import { Image } from 'astro:assets';
import heroImage from '@/assets/hero.jpg';
---
<!-- Astro automatically converts to WebP/AVIF, adds srcset -->
<Image
src={heroImage}
alt="Description"
width={1200}
height={600}
format="avif"
quality={80}
/>
For external CMS images — via <Image src={url} /> with domains configured in astro.config.mjs.
Incremental builds for large sites
With thousands of pages, full rebuilds take minutes. Solutions:
- Astro Content Collections with caching — only changed pages rebuild
- Turbo Remote Caching — cache builds between CI runs
- Partial builds via webhook: Contentful/Sanity triggers deploy only on relevant content changes
# Netlify: rebuild only on specific CMS field changes
{
"build": {
"command": "npm run build",
"publish": "dist"
},
"functions": {
"directory": "netlify/functions"
}
}
Deployment
SSG site is a directory of static files. Deploy anywhere:
- Cloudflare Pages — free tier, 500 builds/month, global CDN
- Netlify — simple workflow, built-in forms and functions
- Vercel — optimal for Next.js
- GitHub Pages — via Actions for open-source projects
- S3 + CloudFront — for AWS infrastructure with full control
Implementation timeline
- Week 1: tool selection, project structure, content schema, design system
- Week 2: page templates, CMS integration, SEO (sitemap, robots.txt, OpenGraph)
- Week 3: image optimization, Search (Pagefind or Algolia DocSearch), deployment pipeline
- Week 4: performance testing, webhook rebuild setup, content team training







