Skip to content

Deploy to GitHub Pages: Fumadocs latest + Sphinx-built legacy versions - #3

Merged
kyleconroy merged 1 commit into
mainfrom
claude/github-pages-docs-workflow-qvqj4w
Aug 27, 2026
Merged

Deploy to GitHub Pages: Fumadocs latest + Sphinx-built legacy versions#3
kyleconroy merged 1 commit into
mainfrom
claude/github-pages-docs-workflow-qvqj4w

Conversation

@kyleconroy

Copy link
Copy Markdown
Contributor

Wires up deployment: deploy.yml builds the whole site and publishes it to GitHub Pages on pushes to main, a daily cron, a repository_dispatch (docs-updated), and manual dispatch.

What gets deployed

  • /en/latest/ — the Fumadocs build of sqlc-dev/sqlc@main docs, as CI already builds it (out/ plus the out-root/ domain-root redirects; out-segments/ is not deployable on a filesystem host and the client falls back to full-page payloads, per the README).
  • /en/vX.Y.Z/ — every version the old Read the Docs site serves (v1.7.0 through v1.31.1, per the RTD API), rebuilt with Sphinx from that tag's own docs/ and fully pinned requirements.txt — exactly as RTD built it — so URLs like docs.sqlc.dev/en/v1.31.1/ keep resolving. The list is frozen in legacy-versions.json; future releases are Fumadocs-built and never go in it. Both the oldest (Sphinx 3.4.3) and newest (8.2.3) toolchains were verified to build cleanly on Python 3.11. Snapshots are immutable, so each tag's built HTML is cached (actions/cache); a miss rebuilds in ~2 minutes, and CACHE_EPOCH forces a full rebuild.
  • /en/stable/ — RTD's newest-release alias, generated as redirect stubs mirroring the newest snapshot's page tree.
  • /, /en/ redirects, a regenerated versions.json (drives the version-switcher dropdown), and a 404.html.

Older-version treatment

scripts/assemble-site.mjs injects into every legacy Sphinx page:

  • an "older release" banner at the top of the content area linking to /en/latest/ (inserted after the theme's <div role="main">, which is present and unique across all sphinx_rtd_theme versions in range; rediraffe redirect stubs are skipped);
  • a search-engine hint in the docs.djangoproject.com style: rel=canonical to the same path under /en/latest/ when that page still exists there (old inbound links keep passing ranking signal to the current docs), noindex when it doesn't (genindex.html, search.html, removed pages) — so old releases never show up in search results.

components/version-banner.tsx bakes the same banner into any future Fumadocs-built versioned snapshot (any NEXT_PUBLIC_BASE_PATH other than /en/latest); those already set noindex at build time.

A missing snapshot fails the deploy loudly rather than silently dropping published URLs.

Tested

  • Real Sphinx builds of v1.7.0 and v1.31.1 plus a real Fumadocs build of main, assembled locally and spot-checked: banner placement, exactly one canonical per page (v1.31.1: 39 canonical / 2 noindex; v1.7.0: 18 / 3), stable stubs, root redirects, versions.json.
  • A NEXT_PUBLIC_BASE_PATH=/en/v9.9.9 build renders the in-app banner and noindex.
  • npm run types:check passes; both workflow YAMLs parse.

One-time setup for cutover

Settings → Pages → source "GitHub Actions", custom domain docs.sqlc.dev; then point the DNS record at GitHub Pages instead of Read the Docs. Still to be added upstream: a small workflow in sqlc-dev/sqlc that sends the docs-updated dispatch on pushes to main touching docs/**.

🤖 Generated with Claude Code

https://claude.ai/code/session_014SnbcV34MHXfFMKSiAjkLY


Generated by Claude Code

deploy.yml publishes the whole site to GitHub Pages on pushes to main, a
daily cron, and a docs-updated repository_dispatch:

- /en/latest is the Fumadocs build of sqlc-dev/sqlc@main, as before.
- Every tag the old Read the Docs site served (v1.7.0..v1.31.1, frozen in
  legacy-versions.json) is rebuilt with Sphinx from that tag's own docs/
  and fully pinned requirements.txt, so /en/vX.Y.Z/ URLs keep resolving.
  The immutable HTML is cached per tag; a miss rebuilds in ~2 minutes.
- scripts/assemble-site.mjs stitches the artifacts into one tree and
  injects, into every legacy page, an "older release" banner plus a
  search-engine hint in the docs.djangoproject.com style: rel=canonical to
  the same path under /en/latest when it still exists there, noindex when
  it does not. It also generates /en/stable redirect stubs (RTD's
  newest-release alias), versions.json for the version switcher, and a
  404 page. Any missing snapshot fails the deploy loudly.
- components/version-banner.tsx bakes the same banner into future
  Fumadocs-built versioned snapshots (any NEXT_PUBLIC_BASE_PATH other
  than /en/latest).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014SnbcV34MHXfFMKSiAjkLY
@kyleconroy
kyleconroy merged commit b60e6c7 into main Aug 27, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants