feat(docs): AI-ready docs UX, full-body search, pm tabs, and content overhaul - #507
Conversation
…overhaul
Research-driven polish across the whole docs site (research doc:
docs/superpowers/specs/2026-07-28-docs-polish-research.md), followed by a
Codex adversarial review whose 8 verified findings are all fixed here.
Site / UX:
- Copy-page dropdown on every docs page: Copy as Markdown, View .md,
Open in ChatGPT / Claude (raw .md twins were already served, now surfaced).
- /llms-full.txt per locale (full-docs bundle); llms.txt linked in footer.
- Full-body + code Cmd-K search: build-time /search-index.<locale>.json
(lazy-fetched), grouped results with matched-heading/snippet sub-rows and
anchor navigation. Slugs replicate markdown-it-anchor exactly (underscores,
inline-HTML dropping, CJK encoding, {#custom-id}, -1/-2 dedup).
- Synced package-manager tabs (::: pm) with per-bar radio groups (keyboard/
ARIA-correct), group-local :has() CSS, JS cross-bar sync + persistence.
- Branded static 404.html (worker notFound serves it); /docs /blog
/changelog section roots 301 to their first page.
- PageMeta row: last-updated + contributor avatars (per-locale git history,
gravatar fallback) + thumbs feedback links + /edit/main edit links.
- Mobile: "On this page" collapsible, Radix focus-trapped drawer (fixed
z-order so the overlay no longer intercepts taps), sidebar active-item
scroll-into-view, skip-link focus fix, copy-code button visible on
touch/keyboard, localized TOC/theme chrome, translate CTA on the
not-translated banner.
- Deploy CI checks out full history (fetch-depth: 0) so lastmod data is real.
Content (EN):
- Rewrite the v2 -> v3 migration guide (H1, grammar, TL;DR table, steps);
fix triples.defaults key name.
- New pages: Custom async runtime (feature + AsyncRuntime SPI +
napi-async-runtime crate, with an unload-safe example), Web Streams
(+AsyncBlock/AsyncBlockBuilder), Examples index.
- Document type_tag, Either3..Either26, HandleScope/EscapableHandleScope,
@napi-rs/wasm-runtime, namespaces; correct with_dispose to success-path.
- De-duplicate function type tables, consolidate dts-header docs, runnable
examples for CLI leaf pages, beginner-ordered concepts sidebar, release
guide surfaced in the beginner path, misc correctness fixes.
Translations (cn + pt-BR):
- Re-sync async-fn, function, promise, async-task, exports to full parity
with the updated English pages (code blocks byte-identical).
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0fd7eb2a92
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Addresses review feedback on #507: - build-search-index: fall back to the frontmatter `title:` when a page has no H1 (cn/pt-BR env + migration-guide pages emitted blank, unmatchable result rows). Verified: 0 blank titles in all 3 locales. - SearchDialog: consolidate ranked results by group label (one CommandGroup per label) via a pure groupSearchResults in lib/docs/search-index — adjacency-only grouping produced duplicate React keys on interleaved rankings. Covered by unit tests.
|
Both review comments addressed in
427/427 tests pass, build green. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 896426fda2
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ack sections Addresses the second round of review feedback on #507 (each verified against the actual @void/md compiler before fixing): - headingText/markdownToPlainText: extract inline code spans BEFORE stripping HTML, so `PromiseRaw<'env, T>` keeps its generic (renderer anchor: promiseraw%3C'env%2C-t%3E) while genuine inline HTML (Promise<T>) is still dropped. Fence markers are removed before the code-span split. - Strip the byte-0 <script> island block before frontmatter everywhere (markdownToPlainText, pageTitle, pageDescription) and tolerate leading blank lines: script-first pages (webassembly, announce-v2/v3) no longer leak YAML into the searchable body and now get title + description. - SearchDialog fallback (metadata index, e.g. vite dev): derive the result section from the locale-stripped leaf, so cn/pt-BR fallback entries group under Docs/Blog instead of a literal locale-code group.
|
Second review round addressed in
432/432 tests pass, build green. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b079b4f88c
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ile TOC width Third round of review feedback on #507 (all verified first): - streams: add `use napi_derive::napi;` to the standalone lib.rs examples (bindgen_prelude does not re-export the proc macro — the docs' own class/ threadsafe-function pages already follow this convention) and import `createReadStream` from node:fs in the index.mjs example. - pageTitle: run the H1 through the same inline-markup extraction as headings — titles like `\`Reference\` / \`WeakReference\`` no longer display backticks in the dialog. - SearchDialog: render CommandEmpty only after the index fetch resolves, so "No results found" no longer flashes next to the loading row. - PageActions/DocsLayout: stretch the island wrapper to the column width ([&>div]:w-full + w-full root), so the mobile "On this page" <details> spans the main column instead of shrink-to-fit right-aligned.
|
Third review round addressed in
433/433 tests pass, build green. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dc2a906028
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| .map((part) => | ||
| part.length >= 2 && part.startsWith('`') && part.endsWith('`') | ||
| ? part.slice(1, -1) | ||
| : part.replace(/<[^>]+>/g, ' ').replace(/(\*\*|~~|\*)/g, ' '), |
There was a problem hiding this comment.
Preserve fenced code while stripping HTML
The inline-code split does not protect fenced code because the fence markers were already removed, so every code sample passes through the HTML-tag regex. Generic types such as Box<dyn AsyncRuntimeGuard + '_> disappear from the new async-runtime index, and a comparison such as if n <= 1 can make the regex consume multiple lines through the next >, removing intervening identifiers from full-body search. Unlike the repaired inline-span case, this is fresh evidence from fenced regions; preserve fence contents separately or restrict HTML removal to prose.
Useful? React with 👍 / 👎.
| #[napi] | ||
| pub async fn sleep_then_add(a: u32, b: u32, sleep_ms: u32) -> u32 { |
There was a problem hiding this comment.
Import the attribute macro in the runtime example
Copying this standalone lib.rs example fails because #[napi] is not in scope: the snippet only uses the fully qualified #[napi_derive::module_init] attribute and imports no napi_derive::napi macro. Import the macro or write this attribute as #[napi_derive::napi] so the documented example compiles.
Useful? React with 👍 / 👎.
| <a | ||
| href="/llms.txt" | ||
| className="transition-colors hover:text-primary" |
There was a problem hiding this comment.
Keep footer links in the active locale
On Chinese and Portuguese pages, this hardcoded link always opens the English /llms.txt, despite the build emitting /cn/llms.txt and /pt-BR/llms.txt; the new Docs link is similarly hardcoded to the English route. This affects both localized landing pages and localized docs/blog layouts, so the footer needs route-locale-aware targets without also enabling the landing-only language control.
Useful? React with 👍 / 👎.
The scroll-into-view effect (from #507) unconditionally scrolled the active sidebar item to 1/3 from the top on every page mount. Since navigation is a full page load, the whole sidebar visibly jumped after EVERY nav click — even when the clicked item was already on screen (reported as a layout shift). Use nearest-edge semantics instead: only adjust scrollTop when the active item is outside the visible area (48px margin), bringing it just into view. An already-visible item leaves the scroll position untouched, so clicking between visible pages no longer shifts anything. Deep links into long sidebars still reveal the active item. Also skips the adjustment when the item has no box (inside a collapsed group).
Summary
Research-driven polish of the whole docs site (4 parallel audits: content & IA, napi-rs feature coverage, UX/frontend code, external best practices — research doc included at
docs/superpowers/specs/2026-07-28-docs-polish-research.md), followed by a Codex adversarial review whose 8 findings were each verified against the code and fixed in this branch.AI-era affordances
.mdtwins were already served — now reachable from the UI)./llms-full.txtper locale (full-docs bundle for agents);llms.txtis now linked from the footer.Search
/search-index.<locale>.json, lazy-fetched on first ⌘K (replaces title/headings-only in-bundle index).#anchornavigation. Slugs replicatemarkdown-it-anchorexactly (verified against the real compiler: underscores kept, inline HTML dropped, CJK percent-encoded,{#custom-id}honored,-1/-2dedup).UX
::: pm): CSS-only switching with per-bar radio groups (keyboard/ARIA correct), group-local:has(), JS cross-bar sync + localStorage persistence; live on getting-started + simple-package in all 3 locales.notFoundserves the static/404.html);/docs,/blog,/changelogsection roots 301 to their first page instead of bare-404ing./edit/mainedit links.fetch-depth: 0so git-derived page metadata is real.Content (EN)
triples.defaultskey name).async-runtimefeature +AsyncRuntimeSPI +napi-async-runtimecrate, with an unload-safe example that joins workers beforeshutdownreturns) · Web Streams (+AsyncBlock/AsyncBlockBuilder,with_disposedocumented as success-path) · Examples index.type_tag,Either3..Either26,HandleScope/EscapableHandleScope,@napi-rs/wasm-runtime, namespaces.functiontype tables, consolidated dts-header docs to one canonical page, runnable examples for CLI leaf pages, beginner-ordered concepts sidebar, release guide surfaced in the beginner path.Translations (cn + pt-BR)
async-fn,function,promise,async-task,exportsre-synced from ~30–67% to full parity with the updated English pages (code blocks byte-identical, heading structure matched).Verification
yarn buildgreen; artifacts confirmed indist/client(search-index ×3, llms-full ×3, 404.html, sitemap, llms.txt)./docs→ 301, cnPromiseRawtranslation live.with_disposeclaim, search slugs/body cap, en-only lastmod + shallow CI, desktop-hidden PageMeta, radio-group a11y,triples.default) verified and fixed here.Deferred (intentionally)
/llms-full.txtcovers the agent use case for now).