Multi-version docs: local preview#

Note

This page documents the preview workflow on the feat/versioned-docs-preview branch. The full release plan is in MADDENING/docs/developer_guide/versioned_docs.md. The version switcher is off by default — CI keeps deploying the single-version site. To preview the multi-version layout locally, opt in with DOCS_MULTIVERSION=1 (the Makefile targets below do this for you).

Quick start#

cd MICROROBOTICA/docs

# One-shot build of every version + serve locally
make preview-versions     # builds, then runs http.server on :8000

# Open http://localhost:8000/maddening/ in a browser.
# The version switcher is in the top navbar.

sphinx-build must be reachable. The Makefile auto-detects the sibling shared venv (../../.venv); otherwise activate your docs venv first (source ../../.venv/bin/activate) or pass an explicit make SPHINXBUILD=/path/to/sphinx-build.

The output structure mirrors the production target:

_build/html/
├── index.html                       ← MICROROBOTICA latest
├── _static/switcher.json            ← MICROROBOTICA version list
├── sitemap.xml                      ← MICROROBOTICA sitemap
├── maddening/
│   ├── index.html                   ← MADDENING latest (= main tip)
│   ├── _static/switcher.json        ← canonical MADDENING version list
│   ├── sitemap.xml                  ← MADDENING sitemap (latest only)
│   ├── v0.1/index.html              ← MADDENING v0.1.0 tag
│   └── v0.2/index.html              ← MADDENING v0.2.0 tag
└── mime/
    ├── index.html                   ← MIME latest
    └── _static/switcher.json        ← MIME version list (one entry)

Every version’s HTML references /maddening/_static/switcher.json via a root-relative URL, so v0.1 pages pick up the switcher dropdown even though v0.1’s source tree predates the switcher.

Iterating on docs without committing#

The default make all-versions builds every version from its remote git ref. When you’re editing a docs file on the latest line and want to see the change without committing, point the “latest” tier at your local working copy:

make preview-local MADDENING_LOCAL=/home/you/MSF/msf/MADDENING
# Edit MADDENING/docs/... files, then re-run — <30 s incremental.

Older versions (v0.1, v0.2) still come from git tags — they’re frozen and don’t need re-builds unless you nuke _build/.

What’s running#

Knob

Default

Multi-version build

DOCS_MULTIVERSION env

unset

1

DOCS_VERSION env

unset

the build label (v0.1, v0.2, latest)

DOCS_DEPLOY_BASE env

https://microrobotica.org

http://localhost:8000

PROJECT env

from caller

maddening / mime / microrobotica

MULTIPROJECT_PATH_<PROJ> env

unset → submodule path

tempdir worktree

navbar shows version switcher

no

yes (rendered, fetches JSON at page-load)

The switcher JSON contract: a flat list of {version, name, url, preferred} rows. version is the value that DOCS_VERSION must match for the theme to highlight the row as “current”. preferred: true marks the stable release (the one new visitors should land on if they have no preference).

Canonical URLs and the sitemap#

Multi-version docs publish the same page at several URLs (/maddening/quickstart.html, /maddening/v0.2/quickstart.html, /maddening/v0.1/quickstart.html). To stop search engines treating those as duplicate content, the latest version is declared canonical:

  • conf.py sets html_baseurl without a version segment (.../maddening/, never .../maddening/v0.2/). Sphinx derives every page’s <link rel="canonical"> from it, so a versioned page emits <link rel="canonical" href=".../maddening/<page>"> — it canonicalises to the latest copy of that page.

  • The sitemap is generated by the latest build only. conf.py drops the sphinx_sitemap extension when DOCS_VERSION != latest, so /maddening/v0.1/ and /maddening/v0.2/ ship no sitemap.xml. Only /maddening/sitemap.xml (latest) exists, and that is the one seo/sitemap_index.xml references.

  • seo/robots.txt keeps Allow: / — crawlers must be able to reach the versioned pages so they can see the canonical link and consolidate. Don’t Disallow the version subdirs.

Net effect: search engines index one copy of each page (the latest), and the version switcher is the only way readers reach older docs.

Adding a version#

MADDENING/docs/_static/switcher.json is the source of truth for the MADDENING dropdown; MICROROBOTICA/docs/_static/switcher.json and MIME/docs/_static/switcher.json are the (currently single-entry) lists for the other two. When a project cuts a release:

  1. Tag the release in that project’s repo (e.g. v0.3.0).

  2. Add a row to that project’s switcher.jsonversion is the label, and move preferred: true to the new stable release.

  3. Update the project’s *_VERSIONS line in docs/Makefile, e.g. MADDENING_VERSIONS := v0.1:v0.1.0 v0.2:v0.2.0 v0.3:v0.3.0 latest:origin/main.

  4. Rebuild.

The latest row builds from origin/main; the canonical switcher.json it ships is whatever is on main, so commit the switcher.json edit to main.

Cleaning up#

make clean              # rm -rf _build/
make clean-worktrees    # remove /tmp/msf-docs-worktree-*

clean-worktrees is safe to run anytime — it removes the git worktrees the multi-version build creates under /tmp/. Subsequent builds re-create them on demand.

Knobs that won’t affect production#

Everything in this preview is gated on env vars that default to “production single-version”:

  • make all (no -versions suffix) — unchanged from v0.1 behaviour.

  • CI workflow (.github/workflows/docs.yml) — untouched.

  • The docs/conf.py switcher block is wrapped in if _multiversion: so it’s a no-op without DOCS_MULTIVERSION=1.

To actually ship multi-version, the steps are in MADDENING’s versioned_docs.md § “Rollout sequence” — three small CI changes once you’re ready.

Troubleshooting#

“sphinx-build not found” — activate the docs venv (source ../../.venv/bin/activate) or pass SPHINXBUILD=/path/to/sphinx-build.

“projects/maddening submodule missing” — run git submodule update --init --recursive.

“worktree add failed for … @ origin/…” — the submodule’s local clone hasn’t fetched that branch yet. Run git -C docs/projects/maddening fetch origin --tags and retry.

“worktree at /tmp/… has no docs/index.md (ref too old?)” — the ref you’re trying to build predates the current docs layout. Drop that row from MADDENING_VERSIONS in the Makefile.

Switcher shows nothing in the dropdown — open the browser DevTools network tab and check that /maddening/_static/switcher.json returns 200. It’s served from _build/html/maddening/_static/; the “latest” build is what writes it.

Switcher shows but the current version isn’t highlighted — the version field in switcher.json has to match DOCS_VERSION exactly. The Makefile sets DOCS_VERSION to the LABEL part of the <label>:<ref> pair (e.g. v0.1, v0.2, latest).