Skip to content

docs(website): TypeDoc router 'module' — one API page per entry point (#590) - #610

Merged
ScriptedAlchemy merged 12 commits into
mainfrom
docs/590-typedoc-module-router
Sep 5, 2026
Merged

docs(website): TypeDoc router 'module' — one API page per entry point (#590)#610
ScriptedAlchemy merged 12 commits into
mainfrom
docs/590-typedoc-module-router

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Second PR for #590 (the first, #599, merged as cfdaeca). This one flips the TypeDoc reference from router: 'kind' — one page per exported symbol — to router: 'module' — one page per public entry point — and follows through on every cost the audit's A/B listed. It is deliberately separate so it can be reverted alone.

Why

The audit measured the kind router at 916 API pages per locale (1,832 with the zh mirror), each rendering a 921-item sidebar in SSR: 561 MB of the 602 MB of HTML was sidebar, doc_build was 623 MB, and the entry chunk static/js/index.*.js was 2.23 MB raw / 368 KB gz on every page because virtual-page-data/virtual-routes are O(pages).

What changed

  • website/rspress.config.ts: app.options.setValue('router', 'module') in the existing TypeDoc setup hook. The main entry point's page is /api/index-1: TypeDoc names module pages after their entry point and index.md is the project index; entryModule: 'index' would replace the project index at /api/ (which authored pages and the nav link to), so the suffix stays and the sidebar labels it index. The member title template is gone because the module router renders no member pages.
  • website/docs/{en,zh}/api/_meta.json: flattened from six kind groups to the project index plus module pages. Explicit type: "file" entries labelled by module name, primary entry points first; nested routes/public and test/browser are addressed by their slashed names (no nested _meta.json needed). en and zh are identical.
  • Anchors: TypeDoc's markdown emits #name-1 for 33 members (86 links) whose reflection URL collided with a name it had already reserved, while Rspress assigns ids with github-slugger over the rendered headings in document order — so the first ### Name on a page is #name and those links were dead. alignTypeDocMemberLinks in mirror-api-locale.ts (which already post-processes the generated tree before mirroring it) strips the suffix only when exactly one heading on the target page, at any depth and outside code fences, produces that anchor; anything ambiguous is left as TypeDoc wrote it for the build's anchor check to judge. Result: 1,902 intra-page links, 0 unresolved.
  • Authored links: every authored link into the reference (39 per locale, in reference/configuration.mdx, guide/development/evaluations.mdx, guide/authoring/index.mdx) now targets ../api/<module>.md#<member>; anchors computed with github-slugger over the generated headings in document order, which is exactly what Rspress does, and verified against the built HTML by scripts/check-built-links.mjs.
  • reference/api.mdx (en + zh): describes the module-page layout and maps each public import specifier to its module page.

Before → after (this machine, RSPRESS_PERSISTENT_CACHE=false, link checks on)

kind router (main) module router (this PR)
HTML pages 1,945 105
doc_build apparent size 650.2 MB 31.2 MB
HTML bytes 625.9 MB 12.4 MB
SSR sidebar links on an API page 935 (94 % of the page) 15 (5 %)
Largest page 1,027 KB (zh/api/interfaces/serve-app-command.SpawnServeAppOptions) 754 KB (zh/api/serve-app-command)
Entry chunk static/js/index.*.js raw / gz 2,295,865 / 375,889 490,956 / 95,132
rspress build wall (load ≈ 8 → ≈ 15) 95 s 82 s
docs:site:build CI job 2m55s (#599) 1m42s
Sitemap URLs 1,946 104

Measured with a Playwright + static-server harness kept outside the repo; the built-link checker's count went from 1,838,131 internal links across 1,950 files to 29,759 across 106.

Deslop

gpt-5.6-sol-medium, 5 edits (fe1e127): three doc comments that restated the helper beneath them (headingText, the PageAnchors fields, visibleText) and one zh clause in the agent-bundle/app row that duplicated the row's closing sentence. Nothing to trim in _meta.json, the config, Dependabot, or the other pages.

Self-review

Reviewer: gpt-5.6-sol-medium (implementing lanes: gpt-5.6-sol-medium for the config/anchor lane, cursor-grok-4.6-high-fast for the link rewrites, claude-fable-5-1-thinking-max for the API overview prose and integration). An earlier pass on gpt-5.6-terra-medium did not produce findings (tooling) and is not relied on. Two independent Sol runs on the pre-fix diff (e7450e6) converged on the same two findings:

  1. alignTypeDocMemberLinks could re-point a legitimate link. It approximated the slugger and rewrote any #x-N fragment when one heading produced x — a real #protocol-v1 would have become #protocol-v, with the anchor check still passing. Fixed (d536405): ids are computed with github-slugger's exact algorithm over every heading in document order (the algorithm Rspress bundles), and a fragment is rewritten only when it is actually dead on the target page and its base is a ### member id. 1,907 intra-page links, 0 unresolved, 168 legitimately suffixed links untouched.
  2. Order-dependent authored anchors (#build-2, #validate-1) would keep resolving to the wrong heading if a same-named heading were added earlier. Fixed: check-built-links.mjs now compares the visible label of every authored /api/<module>#<member> link with the text of the heading it lands on (90 links matched in the gate). It caught one real case — the runEvals re-export sentence in reference/api.mdx labelled the link api — corrected in both locales.

No findings on _meta.json nested names (Rspress joins name onto the directory), en/zh parity, generated-reference accuracy, plugin placement, unmounted modules, or the Pages deploy. Second pass after the fixes: one residual on d536405 — the inlined punctuation set was not github-slugger 2.x's full Unicode regex (a ### x😀 heading would slug differently), with the fix "depend on the same slugger Rspress uses". Fixed (9da096a): ids now come from @rspress/shared/github-slugger, the module @rspress/core itself re-exports for its TOC plugin, pinned to the same 2.0.21. A third pass confirms: import resolves under pnpm's strict layout, headingText matches what toc.js feeds the slugger for TypeDoc's headings, lockfile diff is the three added lines, no leftover symbols; one low finding — Dependabot could bump @rspress/core and @rspress/shared separately — fixed (e9e3e65) with an @rspress/* Dependabot group.

After the reviews, main gained #597 (architecture page) and #578 (composite root): rebased, and the architecture page's two ArtifactManifest links (en + zh) were moved to /api/index-1#artifactmanifest (2b1f3ca); the gate is green on the rebased head (0 broken links / 25,864 anchors, 92 member labels matched) and the pages those PRs touched were re-measured at 1440 × 900: no authored fence overflows and the : any hover count is unchanged at 16. One main regression found during that re-check is deliberately not in this PR: #578's home-page artifact tree overflows its ab-compare column at 1440 px — filed as #617.

Second rebase after #614 and #601 landed: reference/api.mdx (en + zh) conflicted with #601's new agent-bundle/app row and "Where to start" bullet — resolved by keeping this PR's three-column table and adding the app row with its module page, and _meta.json (en + zh) lists the new app page. The link/anchor gates (check-built-links.mjs, Rspress dead-link/anchor/parity checks) are intact and the full pnpm docs:site:build was re-run on the merged tree.

Not in this PR

  • Dropping the zh mirror of the API pages (the audit's alternative lever) — the mirror now costs 14 pages, not 916, so it stays.

Final pass on the merged head (fe1e127), claude-fable-5-1-thinking-high, per the owner's 08:30 note: no blocking findings — rebase content, authored links, _meta.json, gate config and deploy all verified (it also ran raw TypeDoc against the plugin: 106 dead #x-1 links before alignment, 0 after, every rewritten label matching its heading). Three hardening items it raised — a constructible three-way FooCode/fooCode/Foo.code collision the dead-only rule would mis-point, the case-insensitive label check, and the "source file" wording for */index.ts entries — landed in #624 since auto-merge had already fired.

Refs #590.

@ScriptedAlchemy ScriptedAlchemy added the skip-changeset PR changes a publishable package but ships no observable change; changeset not required label Sep 5, 2026
@changeset-bot

changeset-bot Bot commented Sep 5, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: fe1e127

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Sep 5, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle@610
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/create-agent-bundle@610
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/rsc-markdown-stream@610
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@610

commit: fe1e127

ScriptedAlchemy added a commit that referenced this pull request Sep 5, 2026
…b-slugger ids; built-link check matches authored API member labels to their headings
ScriptedAlchemy added a commit that referenced this pull request Sep 5, 2026
…ugger Rspress runs, instead of an inlined approximation
@ScriptedAlchemy
ScriptedAlchemy force-pushed the docs/590-typedoc-module-router branch from 9da096a to 2b1f3ca Compare September 5, 2026 08:04
ScriptedAlchemy added a commit that referenced this pull request Sep 5, 2026
…b-slugger ids; built-link check matches authored API member labels to their headings
ScriptedAlchemy added a commit that referenced this pull request Sep 5, 2026
…ugger Rspress runs, instead of an inlined approximation
@ScriptedAlchemy
ScriptedAlchemy marked this pull request as ready for review September 5, 2026 08:16
@ScriptedAlchemy
ScriptedAlchemy enabled auto-merge (squash) September 5, 2026 08:16
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 5, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-05T08:19:47.590613Z e9e3e65 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

cursor Bot pushed a commit that referenced this pull request Sep 5, 2026
…ng, early-continue over one sitePath, collapse nested broken-set if

Co-authored-by: Zack Jackson <ScriptedAlchemy@users.noreply.github.com>
@ScriptedAlchemy
ScriptedAlchemy force-pushed the docs/590-typedoc-module-router branch from 20d0834 to fe1e127 Compare September 5, 2026 09:20
@ScriptedAlchemy
ScriptedAlchemy merged commit f6deab1 into main Sep 5, 2026
16 checks passed
ScriptedAlchemy added a commit that referenced this pull request Sep 5, 2026
…he authored-label check (#610 follow-up) (#624)

* docs(website): anchor rewrite and label check compare the member name exactly; module-page naming covers */index.ts entries (#610 review)

* docs(website): drop a field comment that restated memberName (#624 deslop)
@ScriptedAlchemy
ScriptedAlchemy deleted the docs/590-typedoc-module-router branch September 5, 2026 09:58
ScriptedAlchemy added a commit that referenced this pull request Sep 5, 2026
…oc router) into feat/592-authoritative-manifest
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changeset PR changes a publishable package but ships no observable change; changeset not required

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant