Source: ViewEdit

SoftNav page TOC and hide-page nav entries

Summary

Hubs that use SoftNav with Default UI or Valentus can soft-swap mast, left nav, and article without a full reload. The right-rail page TOC (aside.toc.sidebar) is built once by bundled site.js from article.doc headings. After a soft navigation (for example from a changelog index to an changelog-details orphan page), the article updates but the TOC still lists the previous page’s sections.

This proposal separates two concerns:

  1. Near-term (UI bolt-on): rebuild the page TOC when the article region changes — interim extension @antora-supplemental/soft-nav-page-toc, wired into facto-stack hub profiles.

  2. Medium-term (Antora core / nav model): first-class hide-page entries — routable, xref-able, and searchable, but omitted from the published left nav tree unless explicitly promoted.

Author directive naming

Single author flag: :hide-page: — this page is hidden from the left nav tree only (omitted from nav.adoc); it remains published (URL, xref, search). Not unpublished, not noindex, not access control.

Parent link: :navtree-parent: parent-page.adoc — which nav tree parent should breadcrumbs and contextual left-nav injection use (required when path heuristics such as *-details/ do not apply).

Build-time associations (cross-tree links to hidden subpages): navtree-registry.json beside the component and/or `

navtree-parent-association:` comment lines in nav.adoc (not rendered; parsed at compose time). Page-level :navtree-parent: wins over registry rules.

Do not use for this: :omit-nav:, :nav-hidden: — ambiguous. :orphan: — overloaded with Antora diagnostics.

Migration only (still parsed, not documented for new pages): :hide-from-navtree:, :page-nav-hidden:, :page-nav-parent:.

Composed HTML meta: antora-supplemental:hide-page, optional antora-supplemental:navtree-parent.

Problem (right-rail TOC)

Layer Behavior today

SoftNav

Registers mast, left [data-panel=menu], and article regions; emits soft-nav:loaded and doc-nav:loaded.

Default UI site.js

On initial load, scans heading IDs under article.doc, fills aside.toc.sidebar, attaches scroll-spy.

Gap

Fetched HTML for the target page is never re-run through site.js in the live document; SoftNav does not swap the aside. Users see stale TOC entries (notably on serial index → detail flows).

Not the same bug: orphan pages (omitted from nav.adoc) explain weak left-nav “current page” highlighting on detail URLs; they do not by themselves prevent TOC refresh. Fixing the rail requires rebuild-or-swap after article swap regardless of nav tree membership.

Interim extension (shippable now)

Package: soft-nav-page-toc

  • Publishes _/js/soft-nav-page-toc.js via siteCatalog.addFile.

  • Optionally injects a defer script immediately after ui/js/site.js on each composed page.

  • Listens for soft-nav:loaded / doc-nav:loaded and rebuilds the aside TOC using the same heading selectors Default UI uses (sectN, :not(.discrete), :toclevels from data-levels on the aside).

Requirements for sites:

  • SoftNav loaded from supplemental UI (before consumers that rebind on soft-nav:loaded).

  • Default UI / Valentus layout with aside.toc.sidebar and article.doc.

Upstream ask A — page TOC lifecycle in Default UI

Target: antora-ui-default (and Valentus parity).

  • Export a supported buildPageToc(document) (name negotiable) that rebuilds aside + embedded TOC and rebinds scroll-spy.

  • Document a single navigation event contract (doc-nav:loaded or native equivalent) that fire-and-forget UI scripts can subscribe to after any in-place article swap — not only SoftNav.

  • Optional: register aside.toc as a fourth SoftNav region in chassis docs so fetch-and-replace works without rescanning (rebuild is still the minimal fix).

Upstream ask B — hide-page routable entries

Antora today has no first-class “listed in the site model but hidden from the left nav tree” entry type.

Common author patterns:

  • Orphans — pages under pages/ reachable by URL, xref, and search; omitted from nav.adoc (changelog-details, legal footnotes, print-only explainer pages).

  • Promoted later — same page later added to nav when the story graduates from appendix to first-class doc.

Authors want:

  • Stable URLs and xrefs without expanding the left nav forest (UX and HTML payload on every page share the same baked nav tree).

  • Optional breadcrumb or contextual TOC injection for hidden targets without duplicating 20+ nav lines.

Interim author convention (nav-drift + SoftNav): declare :hide-page: and optional :navtree-parent: changelog.adoc on pages intentionally omitted from nav.adoc. With nav-drift --require-in-nav, marked pages report as nav-hidden-page (intentional), not page-missing-from-nav. SoftNav and @antora-supplemental/soft-nav-page-toc inject parent breadcrumbs, a single nav-tree child under the parent, and matching <meta> tags at build time.

Possible upstream directions (for discussion, not a finished API):

  • Promote :hide-page: in Antora core so generators and UI bundles understand intentional nav-tree omission without CLI scanning.

  • Nav file attribute on xref lines, for example xref:path.adoc[Label, hide-page] (illustrative syntax only).

  • Optional navtree-parent-association metadata in nav files or component registry for parent links when URL structure alone is insufficient.

  • Playbook key, for example site.nav.hidden_pages with explicit allow-list for sitemap/search.

  • Generator output: omit hidden pages from nav-data.js / menu partial but retain them in the content catalog and page manifest.

Performance note: hiding entries reduces left-rail markup size; it does not remove the need to generate detail HTML. A richer optimization (lazy nav subtrees) is out of scope for v1 but pairs naturally with hide-page metadata.

Shipped client behavior (chassis / hub soft-nav.js):

  • Default SoftNav.swapNav = false — left nav tree is not replaced on soft loads; mast + article update in place.

  • SoftNav.rebuildPageToc() runs after every soft navigation (and initial load).

  • SoftNav.scrollToTop = true — cross-page soft nav scrolls the window to the top unless the destination URL has a # hash.

  • Hide-page entries inject a parent breadcrumb (… / Changelog / Detail title) and a single child under the parent nav link on hard and soft loads (:hide-page: + :navtree-parent:).

Upstream ask C — paginated long indices (changelog, release notes)

Long index pages (changelog timelines, exhaustive reference lists) will overwhelm initial HTML download and render cost. Pagination should be on by default for tagged index pages (for example :page-pagination: changelog or :page-tags: paginated-index), with :page-pagination: none to opt out on pages that must stay one URL.

Open design questions (future extension or Antora core):

  • Precalculation — chunk boundaries must be known at publish time (heading-level splits, byte/line budgets, or explicit === page breaks) so the first response stays small before the reader opts into page 2+.

  • URLs — bare URL resolves to page 1; suffix or query distinguishes later pages (for example /changelog/ + /changelog/2/ or ?page=2). SoftNav and canonical links must agree.

  • SoftNav — paginated index segments may soft-load inside the article column while nav + TOC stay stable; TOC might list only the current segment or link sibling pages.

  • Nav tree — do not mirror every changelog day in nav.adoc; keep hide-page details + pagination in the index body.

Non-goals

  • Changing Valentus TOC truncate/fade CSS to mask long labels — serial changelog pages should use heading structure instead.

  • Replacing SoftNav with full SPA routing — Antora remains static-first.

Suggested Zulip post

Post in Antora Zulip → community / general (or UI stream if you prefer):

SoftNav + Default UI: the aside page TOC goes stale after in-component soft navigation because site.js only builds it on full load. We documented a proposal (hide-page nav entries + TOC rebuild lifecycle) here:

Interim bolt-on: https://github.com/antora-supplemental/soft-nav-page-toc — feedback welcome on whether Default UI should export buildPageToc() and standardize doc-nav:loaded.

References