ADR-0010: Quartz v4 on Cloudflare Pages, auto-build on push

Status: Accepted Date: 2026-05-19

Context

The vault must be shareable as a public wiki with graph view, backlinks, and search — using the Obsidian wikilink semantics already in the notes. User has used this stack on a prior project successfully.

Decision

  • Static site generator: Quartz v4 (jackyzha0/quartz)
  • Hosting: Cloudflare Pages
  • Build trigger: Cloudflare Pages native build on push to main (no GitHub Actions)
  • URLs: mirror vault folder structure exactly (see ADR-0008)
  • Domain: theology.menning.cloud (Cloudflare DNS, custom domain wired in CF Pages)

CF Pages build configuration (added 2026-05-20)

CF Pages deploys via Workers Static Assets (Pages deprecated April 2025). wrangler.toml at repo root points CF at the build output:

name = "zettle"
compatibility_date = "2025-01-01"
 
[assets]
directory = "_meta/quartz/public"

CF Pages dashboard settings:

  • Build command: cd _meta/quartz && npm install && npx quartz build -d ../..
  • Deploy command: npx wrangler deploy
  • Non-production deploy command: npx wrangler versions upload
  • Path (root directory): /
  • Node version: pinned via .node-version at repo root (22.16.0)

GitHub Actions not used — CF native build is sufficient.

Install location (added 2026-05-20)

Quartz lives at _meta/quartz/ as a vendored copy (initial git clone --depth 1 with .git removed; updates via re-clone + diff review + commit). The vault content stays at the repo root.

Content directory passed via CLI flag, not config:

cd _meta/quartz && npx quartz build -d ../..              # build to _meta/quartz/public/
cd _meta/quartz && npx quartz build -d ../.. --serve      # local preview at localhost:8080

Build artifacts gitignored: _meta/quartz/public/, _meta/quartz/.quartz-cache/. Node dependencies inherit the existing node_modules/ ignore.

ignorePatterns in quartz.config.ts excludes from publication: _meta/quartz, _meta/rejected-proposals.md, staging, resources-raw, scripts, README.md, .obsidian. Everything else publishes — including _meta/adr/ and CONTEXT.md, because the methodology story is part of what makes this vault interesting to readers.

Alternatives considered for source tracking:

  • Submodule: rejected — submodule UX is painful for contributors and offers no advantage here
  • Subtree: rejected — git subtree pull is technically the right tool, but author won’t touch Quartz often enough to justify the arcana
  • Separate Quartz repo with vault as submodule: rejected — splits CI across repos for no gain

Alternatives considered

  • Obsidian Publish ($10/mo): rejected — proprietary, paid, can’t customize render
  • Digital Garden plugin (oleeskild): rejected — less mature, weaker graph rendering
  • Astro Starlight / MkDocs Material: rejected — more powerful long-term but cost weeks of setup vs Quartz’s afternoon
  • GitHub Pages (instead of CF Pages): rejected — slower global CDN, 1GB site limit (probably fine but Cloudflare is friendlier as the vault grows)

Consequences

  • (+) Free + self-hostable, no monthly tax
  • (+) Native Obsidian wikilink/backlink semantics work without conversion
  • (+) Graph view matches the visual model from idea.md (“see how notes are linked”)
  • (+) Push-build → publishing latency is single-digit minutes
  • (−) Quartz’s render is themable but not infinitely customizable (acceptable)