Skip to content

Migrate from Material for MkDocs to Zensical - #26

Merged
blsmth merged 1 commit into
mainfrom
zensical
Sep 1, 2026
Merged

Migrate from Material for MkDocs to Zensical#26
blsmth merged 1 commit into
mainfrom
zensical

Conversation

@bartTC

@bartTC bartTC commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Switches the docs build from Material for MkDocs to Zensical (v0.0.57), the successor project from the same team.

What carries over unchanged

Zensical reads mkdocs.yml directly, so most of the setup just works:

  • the macros plugin, including our custom apppack_version() macro from main.py
  • the theme_overrides/main.html analytics block (Plausible + Crisp)
  • custom CSS (palette, pricing admonition), tabs, admonitions, !ENV for SITE_URL
  • deployment: output is still a static site in public/, so the S3 + CloudFront flow is untouched

What needed real changes

  1. literate-nav is not supported yet — it silently fell back to an auto-generated nav. Replaced src/_navigation.md with an explicit nav: in mkdocs.yml. The CLI reference pages are generated by apppack docgen and gitignored, so their nav entries are generated alongside them: scripts/generate_cli_nav.py rewrites a marked block in mkdocs.yml, wired into make cli-docs (which CI now calls).
  2. validation.links.absolute_links: relative_to_docs is ignored — absolute .md links would ship as literal broken hrefs. Converted the six affected links to relative links.
  3. exclude_docs is ignored — the nav file leaked into the build and search index; the explicit nav removes the need for it.

Also: dependencies reduced to just zensical; the emoji extension moves from the material.extensions to the zensical.extensions namespace.

Verification

  • Clean build with zero issues from a fresh venv containing only zensical
  • Rendered navigation diffed against the live production site: label-for-label identical (134 entries, including the generated CLI reference)
  • Spot-checked macro expansion, emoji rendering, analytics scripts, pricing admonition, tabbed content, canonical URLs, and the fixed links in the built output
  • zensical serve smoke-tested (note: its port flag is -a localhost:PORT, not --port)

Caveat

Zensical is pre-1.0 and moving quickly; the lockfile pins 0.0.57. Expect the occasional adjustment on future upgrades until 1.0.

Zensical reads mkdocs.yml directly, so most of the setup carries over
unchanged (macros via main.py, the analytics template override, custom
CSS, !ENV, deployment). Three gaps needed real changes:

- literate-nav is not supported yet: replace _navigation.md with an
  explicit nav in mkdocs.yml. The CLI reference pages are generated by
  apppack docgen and not committed, so their nav entries are generated
  too (scripts/generate_cli_nav.py, run by make cli-docs and CI).
- validation.links.absolute_links is ignored: convert the six absolute
  .md links to relative links so they resolve in the built site.
- exclude_docs is ignored: the nav file would leak into the build and
  search index; the explicit nav removes the need for it.

The rendered navigation was verified to be identical to the current
production site. Dependencies are reduced to just zensical; the emoji
extension moves to the zensical.extensions namespace.
@bartTC
bartTC requested a review from dmonroy September 1, 2026 09:52

@blsmth blsmth left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Built this against main with CLI 4.8.2 and probed the branch rather than reading the diff. It holds up — merging, with follow-ups below.

Verified: 112 pages, identical set to main, nav label-for-label identical, all 6 link conversions at the correct depth, macro/analytics/canonical/admonitions/tabs/emoji/CSS all match.

One correction: validation isn't ignored. config.py:616-651 maps not_found and anchors to zensical's own checks, both defaulting to True — I planted a bad anchor and got a warning. Link checking is actually broader than before; only the absolute_links rewrite is unsupported, which is why the 6 conversions were needed. Worth fixing in the description. (Same for macros — it works without mkdocs-macros-plugin via a built-in shim.)

Follow-ups I'll take:

  1. cli-docs as a prereq of build/run — on a fresh clone make build exits 0 and renders 84 CLI nav entries as raw .md hrefs against pages that don't exist. Nav isn't validated, so no warnings.
  2. --strict on make build — needs #1 first, or it fails a fresh clone for the wrong reason.
  3. Nav-omission check in CI — orphan pages build silently now that literate-nav's globs are gone. Passes 112/112 today.
  4. Nits: python3 bypasses the venv; missing encoding="utf-8"; unknown plugins fail silently, which is what made literate-nav break quietly.

Non-blocking: the committed CLI nav block will dirty mkdocs.yml for anyone running make cli-docs with a newer CLI. CI regenerates so prod is safe — intentional, or would a gitignored include be cleaner?

Nice cleanup on the dependency tree, and thanks for diffing the nav against production.

@blsmth
blsmth merged commit af40145 into main Sep 1, 2026
2 checks passed
@blsmth
blsmth deleted the zensical branch September 1, 2026 14:12
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