Repository navigation
Re-evaluate Zensical as the docs builder when it reaches beta/1.0 #60
Description
Activity
- added a commit that references this issue
on Sep 6, 2026 This was generated by AI during triage.
Triage Notes
Parked as
needs-triage: the revisit trigger has not fired.Gate check (2026-09-06): Zensical is at 0.0.59 on PyPI. The issue's snapshot was 0.0.46 on 2026-07-05, so upstream has shipped 13 releases since, but is still 0.0.x and has not reached the beta/1.0 threshold this issue is conditioned on.
Confirmed not started: there is no
zensical.tomlin this repo and no Zensical reference anywhere in the tree. As the body notes, the spike branch was not kept, so the port is a redo frommkdocs.ymlwhenever it happens.The four re-check criteria remain open. I did not re-test any of them against 0.0.59, since the version gate has not fired:
page.is_homepageand siblings exposed to custom templatesvalidationparity for the docs-heavy repos:omitted_files/ orphaned-page detection andabsolute_linksclassicvariant fidelity against the live site- a
not_in_navequivalent, which this repo now relies on to keepdocs/adr/out of the site menu while still building it
Next action: re-run this gate when Zensical announces beta or 1.0. There is no work to do before then, for a human or an agent.
- addedenhancementNew feature or requestNew feature or requestneeds-triageMaintainer needs to evaluate this issueMaintainer needs to evaluate this issue
on Sep 6, 2026 Revisit check — 2026-09-06
Ran the trigger against Zensical 0.0.59. It has not fired. Every claim below is cited to a
primary source: the PyPI JSON API, thezensical/zensicalandzensical/uisource at the stated
tags, zensical.org, mkdocs.org, and squidfunk.github.io/mkdocs-material. Nothing was installed or
built — where docs are silent, the finding is read from source and labelled as such.Paths are repo-relative within the org;
org/means this repo.Verdict: the trigger has not fired — Zensical is still self-described alpha (0.0.59), all three original blockers remain open, and a fourth has appeared (
exclude_docsis unsupported), so keep the issue open with an updated trigger and re-check after the beta release.All findings below apply to Zensical 0.0.59 (released 2026-09-03), its docs at
zensical/docs
commit94cc5b4(2026-09-03), and the bundled theme UIzensical/uiv0.0.27 (2026-09-02),
unless stated otherwise. Delta baseline is 0.0.46/0.0.47 (the spike, 2026-07-05).
Trigger status
Applies to: 0.0.59.
Fact Value Source Latest release 0.0.59, uploaded 2026-09-03T18:40:51Zhttps://pypi.org/pypi/zensical/json(info.version,releases)PyPI classifier Development Status :: 3 - Alphasame Releases since the spike 13 ( 0.0.472026-07-05 →0.0.592026-09-03; no0.0.49)same Repo HEAD 444b71e"chore: release v0.0.59", 2026-09-03https://github.com/zensical/zensical(git log -1)The project's own words, verbatim:
"Zensical follows [semantic versioning] and currently uses 0.0.x versioning
(alpha / development releases). We're approaching a beta release, after
which we'll transition to 0.x versioning. Once we reach a stable 1.0 release,
the standard semantic versioning rules will apply more strictly."
—https://zensical.org/docs/upgrade/#versioning(source:zensical/docs,docs/upgrade.mdL50–53)"Zensical is currently alpha software and we are iterating rapidly."
—https://zensical.org/about/roadmap/, "Foundation" section (read 2026-09-06)No beta or 1.0 date is given anywhere; the roadmap explicitly declines dates ("Rather than
promising concrete dates, we prefer to make our work visible"). Beta has not been reached.Delta since 2026-07-05 that matters to us
0.0.53—strictis now settable inmkdocs.yml/zensical.toml, not just--strict
(https://github.com/zensical/zensical/releases/tag/v0.0.53, "supportstrictconfiguration option (#840)").0.0.56—unresolved_referencesfurther retired: "Please disableunresolved_references-
it is not supported anymore"; autorefs checking moved underinvalid_links
(https://github.com/zensical/zensical/releases/tag/v0.0.56).0.0.58— build-architecture rewrite (ZRX scheduler); six new plugin replacements
(meta,redirects,minify,tags,literate-nav,awesome-nav); 30–40 % less peak memory
(https://github.com/zensical/zensical/releases/tag/v0.0.58).- Nothing in
0.0.47–0.0.59release notes touchespage.is_homepage,exclude_docs,
omitted_files, orabsolute_links.
Blocker 1 —
page.is_homepagein custom templatesApplies to: Zensical 0.0.59 / ui v0.0.27. Status: still broken, and now demonstrably so at the source level.
Not documented anywhere. Zensical's theme-customization page documents
custom_dir, the
block list, and MiniJinja compatibility but publishes no template-context/variable reference at all
(https://zensical.org/docs/customization/, sourcedocs/customization.md). So this is
"not documented", not "documented as absent".Source says it does not exist. In
crates/zensical/src/structure/page.rs(0.0.59), the render
context is built inPage::render_templateas
context! { generator, nav, base_url, extra_css, extra_javascript, config, page => self, ..variables }.
The serializedpageobject isPageData+Page, whose fields are exactly:url,
canonical_url,edit_url,path,title, plus the flattenedMarkdownfieldsmeta,
content,toc(crates/zensical/src/structure/markdown.rs), plusancestors,previous_page,
next_page. There is nois_homepage—grep -rn is_homepageover the wholezensical/zensical
repo at 0.0.59 returns nothing.And Zensical's own theme still references it, so the failure is silent:
zensical/uisrc/base.htmlL89 (tagv0.0.27) reads{% elif page.title and not page.is_homepage %} <title>{{ page.title | striptags }} - {{ config.site_name }}</title>page.is_homepageis simply undefined → falsy → the homepage falls through thepage.meta.title
branch. This is precisely the duplicated<title>the 2026-07 spike papered over.MkDocs documents
is_homepageas aPageproperty ("Evaluates to True for the homepage of the
site and False for all other pages"), with the exact idiom our overrides use —
https://www.mkdocs.org/dev-guide/themes/(Page object reference).Supported way to special-case the home page today
There is no documented one. From source, the workable, builder-portable expression is a URL
comparison against the navigation homepage:nav.homepageis exposed to templates —NAVIGATION_FIELDS = ["items", "homepage", "hash"]
incrates/zensical/src/structure/nav/view.rsL38, resolved at L161–163 by serializing
navigation.homepage(aNavigationItem, which carriesurl).- So
{% if nav.homepage and page.url == nav.homepage.url %}works under Zensical and equally
under MkDocs (nav.homepageis part of the MkDocs Navigation object).
This is a source-derived workaround, not documented behaviour, and it is not the fix the issue's
trigger asked for.Blast radius, corrected
The issue implies only the org site is affected. In fact all four override files use
page.is_homepage:org/overrides/main.html(twice:htmltitleandextrahead)faststream-outbox/overrides/main.html(extrahead, og/twitter title)modern-di/overrides/main.html(same)lite-bootstrap/overrides/main.html(same)
Under Zensical, each would silently emit a wrong
og:title/twitter:titleon the home page, and
the org site would additionally get a doubled<title>.
Blocker 2 — validation parity
Applies to: Zensical 0.0.59. Status: partially improved (strict is fully there), core gap unchanged.
MkDocs' tree (
https://www.mkdocs.org/user-guide/configuration/#validation; a bare top-level key
such asabsolute_links:sets bothnav:andlinks:) vs Zensical
(https://zensical.org/docs/setup/validation/, sourcedocs/setup/validation.md), cross-checked
against the mapper inpython/zensical/config.pyL613–653 ofzensical/zensical@ 0.0.59:MkDocs key Zensical equivalent Deprecated? Evidence validation.links.not_found(unrecognized_links's sibling)invalid_linksNo — first-class, on by default docs setup/validation.md§invalid_links;config.pyL642 mapsnot_found != "ignore"validation.links.anchors/invalid_link_anchorsinvalid_link_anchorsNo — first-class, on by default docs § invalid_link_anchors;config.pyL644validation.nav.omitted_files(orphan pages)none n/a Not in Zensical's docs at all; config.pyL625–626 comment: "we only support validation of links right now, as navigation will change significantly". Officially acknowledged as an open backlog item:https://github.com/zensical/backlog/issues/63(OPEN, opened 2025-11-20) — "Right now, Zensical [does] not warn about Markdown pages that are not referenced in the navigation … as MkDocs does"validation.{nav,links}.absolute_links(incl.relative_to_docs)none n/a Absent from setup/validation.md; not in the mapper's key set (config.pyL614–622), so silently droppedvalidation.links.unrecognized_linksnone n/a Same as above — silently dropped --strictzensical build --strict, andstrict: trueinmkdocs.ymlsince 0.0.53No docs § "Strict mode"; https://github.com/zensical/zensical/releases/tag/v0.0.53— (Zensical-only) unresolved_references,unresolved_footnotes,unused_definitions,unused_footnotes,shadowed_definitions,shadowed_footnotesYes — docs: "The following checks have been deprecated in their current form"; 0.0.56 notes go further: unresolved_references"is not supported anymore"docs § "Deprecated checks"; release v0.0.56 Two behaviours worth knowing, both from
python/zensical/config.py@ 0.0.59:- Unsupported validation keys are silently ignored — the mapper only reads
links,not_found,
anchors, and Zensical's own eight keys ("We only support a subset of MkDocs' validation
settings, so we ignore the ones we don't support", L639–640). No warning is emitted. - MkDocs' three-level severities collapse to booleans: anything other than
"ignore"means "on".
warnandinfoare indistinguishable.
Replacement is promised but unshipped: the deprecated checks will "be replaced with functionally
equivalent ones once we publish our Python Markdown parser and integrate it with Zensical"
(docs/setup/validation.md). Nothing in the docs promises replacements foromitted_filesor
absolute_links.What
faststream-outboxactually depends onfaststream-outbox/mkdocs.ymldeclares, as top-level (i.e.
nav-and-links) keys:validation: omitted_files: warn absolute_links: warn unrecognized_links: warn anchors: warn
CI runs
just docs-build→uvx --with-requirements docs/requirements.txt mkdocs build --strict
(faststream-outbox/justfileL56, invoked by
.github/workflows/docs.yml).modern-diandlite-bootstrapcarry the identicalvalidation:
block; the org repo has none and relies onmkdocs build --strictalone
(org/.github/workflows/ci.yml,deploy.yml).Net effect of switching that repo to Zensical today:
--strictstill fails the build, and
anchorsstill maps, but three of its four declared checks vanish without a warning — orphaned
pages, absolute links, and unrecognized relative links stop being caught. Because
validation.omitted_filesis what currently keepsdocs/agents/anddocs/adr/honest alongside
exclude_docs, that is a real regression in the repo the issue itself calls the hard case.
Blocker 3 —
classicvariant fidelityApplies to: Zensical 0.0.59. Status: resolved as far as primary sources can settle it —
classicis documented, current, and recommended for exactly our case.- Two variants exist,
modern(default —variantis commented out in the bootstrap config,
python/zensical/bootstrap/zensical.tomlL22) andclassic. - "The
classicvariant preserves the appearance of Material for MkDocs, while both variants
retain the same HTML structure. We recommend usingclassicwhen moving an existing Material for
MkDocs project or when custom CSS and JavaScript depend on its established appearance."
—https://zensical.org/docs/compatibility/mkdocs/migration/#theme-variant - "Zensical supports the complete settings surface and provides a
classictheme variant that
preserves the look of Material for MkDocs"; "[additional CSS] and [JavaScript] work without
changes when using theclassictheme" —https://zensical.org/docs/compatibility/mkdocs/ - Still actively maintained, not frozen: 0.0.47's notes describe features integrating "with the
theme in bothclassicandmodernvariants"
(https://github.com/zensical/zensical/releases/tag/v0.0.47); the roadmap states "You can keep
the original look of Material for MkDocs, or opt into the new, modern design" and claims
"Identical HTML output" (https://zensical.org/about/roadmap/).
Caveat: pixel-level fidelity against our live sites is a claim only a build can settle, and the
spike branch was not kept. Nothing in primary sources contradicts it; nothing verifies it either.
Config-surface gap check
Union of keys actually used across
org/,faststream-outbox/,modern-di/,lite-bootstrap/
(the only four repos with amkdocs.yml;chat-app,modern-di-faststream,modern-di-pytest,
litestar-sqlalchemy-templatehave none). Status is for Zensical 0.0.59.Key (as used) Zensical equivalent Evidence site_name,site_url,site_descriptionYes, same names https://zensical.org/docs/setup/basics/repo_url,repo_name,edit_uriYes, same names https://zensical.org/docs/setup/repository/docs_dirYes setup/basics.md#docs_dirnavYes, unchanged https://zensical.org/docs/compatibility/mkdocs/migration/exclude_docsNO — documented as unsupported migration.md § "Unsupported settings" lists exclude_docs,draft_docs,not_in_nav,hooks,remote_branch,remote_name; tracked athttps://github.com/zensical/backlog/issues/65(OPEN, 2025-11-22). Source confirms: noexclude_docshandling inpython/zensical/config.py, and the RustProjectstruct (crates/zensical/src/config/project.rsL48) has nodeny_unknown_fields, so the key is silently dropped —docs/adr/anddocs/agents/would be published with no warningtheme.name: materialYes — "we deliberately keep the name of the default theme as material"https://zensical.org/docs/customization/#theme-configurationtheme.custom_dirYes; resolved relative to the config file https://zensical.org/docs/customization/#configuring-overridestheme.logo,theme.faviconYes https://zensical.org/docs/setup/logo-and-icons/theme.icon.{edit,view,repo}Yes https://zensical.org/docs/setup/repository/theme.palette(list,media/`scheme: defaultslate /toggle.icon/toggle.name`)Yes palette.primary: custom+accent: custom(CSS vars inextra_css)Yes, documented idiom https://zensical.org/docs/setup/colors/(primary: custom+--md-primary-fg-color*in extra CSS)theme.features:navigation.instant,.top,.sections,.expand,.footerYes https://zensical.org/docs/setup/navigation/,.../setup/footer/theme.features:header.autohide,announce.dismissYes https://zensical.org/docs/setup/header/theme.features:content.code.copy,content.code.annotateYes https://zensical.org/docs/authoring/code-blocks/theme.features:content.action.edit,content.action.viewYes https://zensical.org/docs/setup/repository/theme.features:search.suggest(org only)Undocumented but implemented Absent from docs/setup/search.md(onlysearch.highlightis documented); present in the UI's feature union,zensical/uisrc/assets/javascripts/_/index.tsL58extra_cssYes https://zensical.org/docs/customization/#additional-cssextra.social(icon/link/name)Yes https://zensical.org/docs/setup/footer/validation.*Partial — see Blocker 2 markdown_extensions:admonition,attr_list,def_list,md_in_html,toc.permalinkYes, all listed as natively supported https://zensical.org/docs/compatibility/markdown/python-markdown/markdown_extensions:pymdownx.{highlight(anchor_linenums,line_spans,pygments_lang_class), inlinehilite, snippets, superfences, tabbed(alternate_style), details}Yes, all listed with those exact options https://zensical.org/docs/compatibility/markdown/python-markdown-extensions/pymdownx.emojiwith!!python/name:material.extensions.emoji.*(org only)Yes — the YAML tag ports, and the material.namespace is auto-rewrittenDocs prescribe !!python/name:zensical.extensions.emoji.twemoji(.../python-markdown-extensions/#emoji); source shim rewrites it for you:python/zensical/config.pyL177–181 replaces"material.extensions"→"zensical.extensions"(andmaterialx→zensical.extensions) in the raw YAML before parsing. The rewrite is source-level, not documentedmarkdown_extensions:codehilite: {use_pygments: true}(all three project repos)Undocumented; source shows pass-through Not listed among supported extensions on either compatibility page. python/zensical/config.py::_convert_markdown_extensions(L1197+) has no allowlist andpython/zensical/markdown/render.pyL76–79 hands the names straight toMarkdown(extensions=...), so the stock Python-Markdown extension would load. Rendering/styling parity unverifiedplugins.llmstxt(modern-dionly)NO Not in the supported-plugin list ( https://zensical.org/docs/compatibility/mkdocs/plugins/, which covers autorefs, awesome-nav, glightbox, literate-nav, macros, markdown-exec, meta, minify, mkdocstrings, offline, redirects, search, section-index, table-reader, tags). Tracked athttps://github.com/zensical/backlog/issues/83(OPEN, 2026-01-05)Template overrides using MiniJinja-incompatible Jinja Mostly fine — Material adapted its templates by 9.6.18; our repos pin mkdocs-material>=9.7.5(org) />=9,<10(projects)https://zensical.org/docs/compatibility/mkdocs/migration/#templates-and-overridesFlagged — no documented equivalent:
exclude_docs(silently ignored),validation.omitted_files,
validation.absolute_links,validation.unrecognized_links(all silently ignored),
plugins.llmstxt. Flagged — undocumented but working per source:search.suggest,
codehilite, thematerial.extensions.emojinamespace rewrite, andnav.homepageas an
is_homepagesubstitute.The issue's closing note is stale:
not_in_navis no longer used anywhere in the org. Three of
the four repos useexclude_docsinstead (org/mkdocs.yml"Repo-internal docs that must not be
published";faststream-outbox/mkdocs.yml,modern-di/mkdocs.ymlexclude/agents/and/adr/;
lite-bootstrap/mkdocs.ymlhas neither key). That swap makes the situation worse, not better:
not_in_navandexclude_docsare both unsupported, butexclude_docsfailing open means unlisted
internal pages get published, not merely mis-navigated.
Next step
- Do not port. Re-check when Zensical announces beta (
https://zensical.org/docs/upgrade/#versioning
is where the wording will change; the newsletter and GitHub releases are the announcement channels). - Update the issue's revisit trigger to four items, in this order of severity:
exclude_docssupport —https://github.com/zensical/backlog/issues/65(new; blocks the three sites that use it, fails silently by publishing internal docs)- orphaned-page detection to replace
validation.omitted_files—https://github.com/zensical/backlog/issues/63 page.is_homepage(or a documented template-context reference) — affects all fouroverrides/main.html, not just the orgvalidation.absolute_links/unrecognized_links
Drop thenot_in_navnote and the "classic variant fidelity" item; replace the latter with a
one-line "verify by build" task, sinceclassicis documented, recommended for migrations, and
still actively shipped.
- Cheap watch: subscribe to
zensical/backlog#65and#63rather than re-running this survey. - Optional, low-cost hedge available today and independent of any migration: replace
page.is_homepagein the fouroverrides/main.htmlfiles with
page.url == nav.homepage.url, which is correct under MkDocs now and would survive a future port.
Item 4 above is now tracked separately as #71 — it is correct under MkDocs today and does not
depend on this issue.This was generated by AI during triage.
Revisit check — 2026-09-15
Trigger has not fired. Kept
enhancement+needs-triage, nothing to port.Fact Value Source Latest release 0.0.62, uploaded 2026-09-13https://pypi.org/pypi/zensical/jsonReleases since last check (0.0.59) 3: 0.0.60,0.0.61,0.0.62same PyPI classifier Development Status :: 3 - Alphasame Versioning wording unchanged: "approaching a beta release", no date https://zensical.org/docs/upgrade/#versioningbacklog#65 ( exclude_docs)open, no activity since 2025-11-22 https://github.com/zensical/backlog/issues/65backlog#63 (orphan pages / not_in_nav)open, no activity since 2025-11-20 https://github.com/zensical/backlog/issues/63backlog#83 ( llmstxt)open, no activity since 2026-01-05 https://github.com/zensical/backlog/issues/83Release notes for 0.0.60–0.0.62 cover the
table-readerplugin, page and anchor redirects,mkdocs-callouts, and relaxed plugin-settings validation. None touchexclude_docs,omitted_files,absolute_links,unrecognized_links, or the template context.Redundancy check: no
zensical.tomland no Zensical reference anywhere in the org tree. Not started.Body corrections
- Blast radius has grown. Eight repos now carry a
mkdocs.yml, not four: the original.github,faststream-outbox,modern-di,lite-bootstrap, plushttpware,faststream-redis-timers,semvertag,that-depends. Seven of the eight useexclude_docs(all butthat-depends), and six declare avalidation:block (.githubandthat-dependsdo not). Trigger items 1 and 2 therefore block seven and six repos respectively, not three. - Item 3 (
page.is_homepage) is now worked around everywhere. Replace page.is_homepage with a builder-portable homepage check in every overrides/main.html #71 covered four repos on 2026-09-06; the three repos added since are fixed in httpware#126, semvertag#70 (both merged) and faststream-redis-timers#76 (open, blocked on unrelated lint drift). The underlying gap — no documented template context in Zensical — is unchanged, so the item stays on the trigger list as "re-verifynav.homepageat port time".
Next re-check when the versioning wording at
https://zensical.org/docs/upgrade/#versioningchanges, or backlog#65 / #63 move.- Blast radius has grown. Eight repos now carry a
Checked 2026-10-03 against 0.0.67. Still blocked, but two things moved.
- Release line: per Upcoming changes, 0.1.0 ships on 2026-11-05 and leaves the 0.0.x alpha series. 1.0 is described as a later formality, so 0.1.0 is the real revisit trigger, not "beta/1.0".
- Deadline: Material for MkDocs critical maintenance is extended to 2027-05-05. That puts a date on the migration.
The four blockers:
exclude_docs: Supportexclude_docsanddraft_docssettings inmkdocs.ymlzensical/backlog#65 is still open.- Orphaned-page detection: Support
not_in_navsetting inmkdocs.ymlzensical/backlog#63 is still open. page.is_homepage: not re-checked here.plugins.llmstxt: Support formkdocs-llmstxtplugin functionality zensical/backlog#83 was closed as completed on 2026-10-02. Its replacement shipped in 0.0.67, so this one needs a build check, not a wait.
- addedblockedWaiting on an external dependency or upstream changeWaiting on an external dependency or upstream change
on Oct 3, 2026
Migrated from
planning/deferred.md, retired in the move to the PR-body-as-spec convention (#50).What
Replace Material for MkDocs with Zensical (same team) as the builder for the
org site and the per-project docs sites.
Validated feasible against Zensical 0.0.46 on 2026-07-05: a
zensical.tomlmirror ofmkdocs.ymlplus a one-block
overrides/main.htmltweak (dedupe the homepage<title>by title text) builds thecurrent site cleanly under both builders. The spike branch was not kept — redo the port from
mkdocs.ymlwhen revisiting.Why it was deferred
Zensical is pre-1.0 alpha with gaps versus our current setup. Last checked 2026-09-06 against
0.0.59: still
Development Status :: 3 - Alpha, still "approaching a beta release", no date given.Full findings with sources:
#60 (comment).
Revisit trigger — when Zensical announces beta, re-check these four, in severity order
exclude_docs— documented unsupported(backlog#65), and fails open: the Rust config
struct has no
deny_unknown_fields, so the key is silently dropped anddocs/adr/+docs/agents/get published. Blocks
.github,faststream-outboxandmodern-di, which all rely on it.Hardest blocker, and the one that would do damage rather than break a build.
validation.omitted_files(backlog#63). Also still absent:
absolute_linksandunrecognized_links. All three are silently ignored by the config mapper —no warning.
faststream-outboxis the hard case: it declares all three plusanchors, so threeof its four checks would vanish quietly. Does map already:
--strict(andstrict: trueinmkdocs.ymlsince 0.0.53),invalid_links,invalid_link_anchors.page.is_homepage, or any documented template-context reference at all — absent from the0.0.59 source, and Zensical publishes no context docs. Affects all four
overrides/main.html;fails silently because Zensical's own theme still references it. Being worked around ahead of
time in Replace page.is_homepage with a builder-portable homepage check in every overrides/main.html #71 (
nav.homepage), which removes the bug from our side but not the underlying gap.plugins.llmstxt(modern-dionly) — unsupported(backlog#83).
Then verify by build:
classicvariant fidelity against the live sites. No longer a blocker onpaper —
classicis documented, explicitly recommended for migrating an existing Material project,and still actively shipped — but the spike branch was not kept, so pixel parity is unverified.
Cheapest watch is subscribing to
zensical/backlog#65 and #63 rather than re-running the survey.