Static Site Generators (SSG)

Programs that turn source files (Markdown + assets + templates) into a static HTML site, deployable from any dumb file server — no runtime, no database, no attack surface beyond the web server itself. The enabling technology under blogs, docs sites, and Digital gardens alike; the reason Markdown won as the authoring format.

How the family slices

  • Templating model — Go-template monoliths (Hugo, Zola) vs component-islands (Astro, Next) vs layout-inheritance (Jekyll, Eleventy). The trade: template-language power vs escaping into a real language when logic grows.
  • Build performance — Hugo/Zola compile-time speed (Rust/Go, sub-second rebuilds) vs the JS bundlers’ dependency graph cost. For a garden of hundreds of notes rebuilt on every commit, build speed is the UX.
  • Content model — file-tree-is-the-site (most) vs graph-native (Quartz: the backlink graph is the product, not a feature).
  • Data sources — Markdown-first vs headless-CMS-first vs MDX-with-components. The garden stays Markdown-first: source of truth is plain files in git, renderers are replaceable.

The generators this homelab runs

  • quartz (OSS) (13.2k★, MIT, TS) — this garden (~/projects/garden-site): turns an Obsidian vault into a published site, translating OFM at build time (wikilinks → slugged links, callouts, graph view). Chosen because the vault is the source of truth, not a CMS.
  • hugo (OSS) (90.0k★, Go) + chirpy theme — the blog (hugo.h.krzysztofkaminski.dev, ~/projects/blog); the hugo-blog skill carries the workflow.
  • zola (OSS) (17.5k★, Rust) — the test blog (zola.h.*, per the zola-blog skill); single binary, everything built-in — the Rust niche-mate of Hugo.

The wider field (repos captured, linked)

  • astro (OSS) (62.9k★, TS) — “the web framework for content-driven websites”; islands architecture — ship zero JS by default, hydrate interactive islands only. The static-site-plus-sprinkles middle path.
  • buildawesome (OSS) (19.9k★, JS) — Eleventy, renamed: repo 11ty/eleventy → 11ty/buildawesome (the API 301-redirects; the capture SKIPs as “exists”). The minimalist counter-position: no client framework, no data graph — directory of templates in any engine → HTML.
  • jekyll (OSS) (51.7k★, Ruby) — the original blog-aware SSG; GitHub Pages’ default, which made it the on-ramp for a decade of blogs. fzakaria.com (Personal websites inspiration) runs bare Jekyll v4.4.1 with hand-rolled CSS — the “no theme, all typography” pole.
  • gatsby (OSS) (55.9k★, React) — the cautionary tale: GraphQL data layer + React island-everything; dominated 2018-2021, then Next took the JS mindshare and Astro took the static-first mindshare. Still maintained (not archived, pushed 2026-09) but decisively lost the future — the garden’s “Gatsby lost” post thesis.

Why static (the argument worth keeping)

  • Deployment: any file server, object storage, or CDN edge — the site is files. No runtime to patch, no DB to back up, nothing to monitor beyond uptime.
  • Ownership: plain files in git = the Golden repo pattern applied to a website; content survives every generator death (the Markdown source outlives the tool).
  • Performance: pre-rendered HTML, cache-everything; the “is a framework needed?” question answers itself for read-mostly sites.
  • The cost: anything dynamic (search, auth, comments) becomes a build-time or client-side problem — Quartz solves search by shipping the index to the client (Quartz search); forms/comments go to external services or get dropped.

Open

  • (open: Astro hands-on — island architecture as the “static site + sprinkles of interactivity” middle path; candidate if a future project needs embedded widgets without a runtime)
  • (open: does the viz artifacts lane (viz.h) want an SSG index page, or stay hand-rolled HTML?)
  • (open: write the “Gatsby lost” blog post — Gatsby lost placeholder; thesis: GraphQL-everything + React-everything was the wrong bet twice, islands beat hydration, build-time beat runtime)

Related: Digital gardens · Markdown won · Quartz search · Personal websites inspiration

The MkDocs saga: maintenance death → hostile rewrite → Zensical (2026-10-12)

USER context at capture, verbatim: “I am long time fan of MkDocs material. There has been some dramas, then maintenance issues but it served me well for couple of projects and first versions of my digital garden - thanks to Mara-Li enveloppe.ovh. Zensical seems interesting but not yet at feature parity.” All three blog posts in the saga captured (squidfunk’s own series), plus obsidian-enveloppe (OSS) (Mara-Li’s Obsidian→GitHub publisher, 909★, Apache-2.0 — the vault-to-MkDocs bridge that powered the garden’s first versions).

The timeline from the captures:

  1. 2024-08 — MkDocs stalls. squidfunk’s “Transforming Material for MkDocs”: MkDocs effectively unmaintained since August 2024 (no releases in over a year, unresolved issues/PRs piling up), maintainership changed mid-2024, and a ground-up rewrite began that “does not require or support plugins.” squidfunk raised objections “to no avail” and immediately started building what became Zensical.
  2. 2025-11 — Zensical announced. Next-gen SSG by the Material team, “distilled from a decade of experience,” built to beat MkDocs’ architectural limits. Compatibility first: natively reads mkdocs.yml, smooth migration path, subset of plugins supported with parity in progress. MIT, sponsorware dropped, commercial lane = Zensical Spark.
  3. 2026-02 — MkDocs 2.0 fallout. The pre-release confirms: incompatible with Material for MkDocs, no plugin system (“removing plugin support to simplify the codebase” — squidfunk’s answer: the 300-plugin ecosystem “is one of the cornerstones of MkDocs’ success”), pre-rendered-HTML navigation that makes tabs/collapsible nav “technically impossible,” closed contribution model (“maintainer-driven issues,” no community PRs), initially unlicensed (later MIT, with license-change reserved), TOML config with no migration path from mkdocs.yml. Material 9.7.2+ prints a build warning (NO_MKDOCS_2_WARNING=1 to silence).

Why forking MkDocs was rejected (the keepable architecture lesson): every plugin depends on the mkdocs package name, so a real fork means forking all 300+ plugins — “like moving an entire city at once”; import-system interception “only preserves the ecosystem on the surface” (Python has no visibility boundary, so every internal is plugin surface); and the deep problem is no model of data dependencies — plugins share mutable state at fixed sync points, making parallel builds, differential builds, multi-project coordination, meaningful caching, and fast preview structurally impossible without a ground-up rewrite. Zensical’s module system (ZAP-007) is that rewrite: modules declare reads/writes so the build graph exists.

Field updates: zensical (OSS) now 5.9k★, MIT, written in Rust (not a Python fork — a new engine); mkdocs-material (OSS) 27.6k★, MIT, the biggest docs theme alive. The SSG family portrait gains its maintenance-mortality entry: MkDocs 1.x is the walking dead, 2.0 is a different tool with the same name, Zensical is the continuity play but “not yet at feature parity” (user verdict) — the garden-relevant trio stays Quartz/Hugo/Zola, with Zensical as the watch-item for docs-lane projects wanting the Material lineage.