modern-react-spa

Chapter 23

SSG Tools for React

Picking an SSG for React in 2026 — Astro, Next.js static export, Vite SSG, Gatsby today, smaller players, with a clear picker.

Published 2026-05-23

🎯 Chapter Goal — After this chapter you can pick the right SSG tool for your project (Astro for content-forward sites with islands; Next.js static export for Next-flavored teams; Vite SSG for SPA-style codebases; Gatsby only in specific scenarios), and recognise what each does well and badly.

🧭 Prerequisites — Ch 22 (SSG spectrum). Ch 17 (Vite) for the Vite-SSG option.


🔹 23.1 Astro — islands, partial hydration

https://astro.build — content-first framework. Pages are .astro files (HTML + JS frontmatter); interactive widgets are “islands” of React (or Vue, Svelte, Solid) within an otherwise-static page.

---
import { TenantSwitcher } from '../components/TenantSwitcher.tsx';
const { tenants } = await fetch('/api/tenants').then((r) => r.json());
---
<html>
  <body>
    <h1>Acme docs</h1>
    <p>Static content rendered at build time.</p>

    <!-- Only this widget ships JS; the page around it is HTML-only -->
    <TenantSwitcher client:visible tenants={tenants} />
  </body>
</html>

Astro wins when:

  • The site is mostly content (docs, blog, marketing) with sprinkles of interactivity.
  • Page-weight matters — Astro ships zero JS by default; only islands cost bundle.
  • You want React for the dynamic parts but don’t want a React-first framework’s overhead.

Astro loses when:

  • The app is mostly interactive (dashboards, admin tools).
  • You need server components / per-request rendering — Astro’s SSR is fine but not its strength.
  • Your team wants pure React DX — Astro’s .astro files are a learning curve.

Cross-link Ch 24 for using Astro as the marketing-site wrapper around a React SPA.


🔹 23.2 Next.js App Router in static-export mode

https://nextjs.org/docs/app/building-your-application/deploying/static-exports

Next.js can produce a fully-static build:

// next.config.js
module.exports = { output: 'export' };

Every page renders to HTML at build time. No Next.js runtime needed for serving — drop out/ into any static host.

Static-export Next wins when:

  • Team already knows Next.js; the App Router patterns transfer.
  • You want React Server Components for content composition without a runtime server.
  • You’ll move to ISR / SSR later — same codebase, change one config line.

Static-export Next loses when:

  • You want Astro’s zero-JS-by-default model — Next always hydrates the page.
  • You don’t need Next’s full surface (data fetching, image optimization, middleware) — you’re carrying overhead for nothing.

🔹 23.3 Gatsby today

https://www.gatsbyjs.com — the early SSG pioneer. Status as of 2026: declining. Netlify acquired it in 2023, has slowed development.

Gatsby still makes sense when:

  • You’re already on Gatsby and the GraphQL data layer fits your model.
  • You need the plugin ecosystem for a specific source (Contentful, Sanity, WordPress) that Gatsby covers exhaustively.

Otherwise: Astro or Next.js static export are the better picks for new projects.


🔹 23.4 Vite SSG — vite-ssg for SPA-style codebases

https://github.com/antfu-collective/vite-ssg — pre-renders a Vite + React SPA’s routes at build time. Same codebase as your SPA; one config addition; you get static HTML.

// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  // package.json: "build": "vite-ssg build"
});

The build pre-renders each route in a headless browser-like environment, emits the HTML, and ships your JS bundle for hydration.

vite-ssg wins when:

  • You have an existing Vite SPA and want SEO benefits on a few routes without adopting a framework.
  • The app is small enough that “render every route at build time” is tractable.

vite-ssg loses when:

  • You have hundreds of dynamic routes (/invoice/:id) — Astro or Next handle this better.
  • You need server-side data per route — vite-ssg pre-renders against static data.

🔹 23.5 Smaller players

  • React Static — mostly dormant; legacy projects only.
  • Eleventy + React — Eleventy is JS-content-focused; React is a renderer option.
  • Docusaurus — purpose-built for documentation sites; React-based. Strong default if your only need is docs.

🔹 23.6 Picking one

NeedPick
Mostly content + a few React widgetsAstro
Already on Next.jsNext static export
Existing Vite SPA, want SEO on routesvite-ssg
Documentation site onlyDocusaurus
Already on Gatsby and not sufferingStay
Hybrid (SSG marketing + SPA app)Astro + Vite SPA (Ch 24)

🪤 Common Pitfalls

  1. Adopting Gatsby for a new project in 2026 — declining maintenance.
  2. Astro for an interaction-heavy app — fights the framework.
  3. Next static export when you actually need SSR — eventually you switch to dynamic mode anyway.
  4. vite-ssg with hundreds of routes — slow builds; consider a real framework.
  5. Skipping the rendering-strategy question (Ch 22) and picking a tool first.

✅ Recap

  • Astro for content-forward, island-based hydration.
  • Next static export for Next teams.
  • vite-ssg for SPA-style codebases that need SEO.
  • Gatsby and others — niche today.
  • Pick the strategy (Ch 22) before the tool.

🔗 Further Reading

In the book — not on the site

Each topic has an 🧠 Under-the-hood subsection — the algorithm, the data structures, what React DevTools surfaces, debugging recipes. Plus a 🧪 hands-on lab per chapter with a starter repo. Reserved for the book.

Topics in this chapter (6)
  1. 23.1 Astro — islands, partial hydration
  2. 23.2 Next.js App Router in static-export mode
  3. 23.3 Gatsby today
  4. 23.4 Vite SSG — vite-ssg for SPA-style codebases
  5. 23.5 Smaller players
  6. 23.6 Picking one