Skip to content

fix(docs): build the On-this-page rail from the compiled MDX toc - #9953

Merged
loopover-orb[bot] merged 1 commit into
mainfrom
fix/docs-toc-from-mdx-9872
Jul 30, 2026
Merged

fix(docs): build the On-this-page rail from the compiled MDX toc#9953
loopover-orb[bot] merged 1 commit into
mainfrom
fix/docs-toc-from-mdx-9872

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Closes #9872 — the last of the 27 react-hooks 7 sites from #9588.

react-hooks/set-state-in-effect is back at error with no suppressions.

The blocker the issue named, resolved

Not every docs page is MDX … and the data and the component are in different routes.

There was a third, which decided the design: the toc cannot travel through the route loader. A toc entry's title is a ReactNode, and 29 of this repo's 451 docs headings carry inline markup (### \wantedPaths` (string list, default: `[]`)`), so those entries are React elements and do not survive the server-function JSON boundary.

So it is read on the client, from the same docsClientLoader cache the page content already resolves through — no second fetch. useChildMatches supplies the compiled path, which only the MDX route's loader has.

What that removes

The DOM scrape, the id back-fill, and the setState in the effect body, together. What remains is an IntersectionObserver for active-section tracking — real external-system work, and it sets state only from the observer callback, never from the effect body.

Two incidental wins: rendering title as a node means a heading keeps its inline code instead of being flattened by textContent; and the scrollMarginTop the effect used to assign in JS is now a CSS class.

Non-MDX routes render no rail — deliberate, per the issue's "or deliberately opt out". The index page's only headings are its card titles, which produced a list of link names rather than a table of contents; the API-reference spike is a standalone widget.

Browser verification, and its limit

Structure verified live at 1400×900 against /docs/fairness-methodology and /docs/ams-fleet-manifest:

check result
rail renders from compiled toc 11 entries on the long page
every anchor target exists in the DOM ✅ all
h2/h3 nesting both levels, correct indentation
inline code in a heading renders as a real <code>, not flattened text
scroll-mt-20 replaces the JS assignment computed 80px

Active-section highlighting could not be exercised there. IntersectionObserver delivers no callbacks in that pane — I confirmed a plain observer with no options also fires nothing, so this is an environment limit, not a defect in the change. That path is covered by unit tests instead (aria-current from a remembered section, and the click path), and I am flagging it rather than implying the whole component was verified end-to-end.

Worth stating plainly: I initially read that silence as a real bug and wrote a code comment asserting it. That was wrong, and the comment now says what is actually known.

The retry loop

The headings are rendered by the page, in a different Suspense boundary from the rail. A single up-front getElementById sweep would observe nothing permanently on any commit where the rail lands first, since the effect's deps do not change when content later appears. Both boundaries suspend on the same cached promise and usually commit together, so this is a guard against an ordering hazard, not a fix for an observed failure — the comment says so. It costs one pass and schedules no frame when the headings are already present, and is bounded so a toc entry whose heading never renders cannot leave a loop running.

Validation

  • ui:test 1,099 passing (7 new), ui:lint and ui:typecheck clean with the rule at error, ui:build green.
  • Backend suite + full checker sweep run on the branch; results in a follow-up comment.

Closes #9872. Follow-up to #9588, which fixed 26 of 27 react-hooks 7 sites.

DocsToc scanned the rendered article for h2/h3, back-filled ids onto any heading
missing one, and read the result into state from an effect. That was the app's
last react-hooks/set-state-in-effect site -- the reason the rule sat at warn --
and it was fragile independently of lint: the rail was a function of the rendered
markup, so a styling change to the article wrapper silently emptied it.

It now renders the page's compiled toc. The rule is back at error with no
suppressions.

WHY THE TOC CANNOT GO THROUGH THE ROUTE LOADER, which is what the issue flagged
as needing resolution first: a toc entry's title is a ReactNode, and 29 of this
repo's 451 docs headings carry inline markup, so those entries are React elements
and do not survive the server-function JSON boundary. It is read on the client
instead, from the same docsClientLoader cache the page content already resolves
through, so this adds no second fetch. useChildMatches supplies the compiled
path, which only the MDX route's loader has.

Rendering title as a node is also a small improvement: a heading like
'wantedPaths (string list)' keeps its inline code, where reading textContent off
the DOM flattened it.

The id back-fill is gone because fumadocs already emits ids that match the toc's
own urls, and the scroll-margin the effect used to assign in JS is a CSS class on
the prose wrapper now.

Non-MDX docs routes render no rail. The index page's only headings are its card
titles, which produced a list of link names rather than a table of contents, and
the API-reference spike is a standalone widget. Deliberate, per the issue's
'or deliberately opt out'.

VERIFIED IN A BROWSER for structure: 11 entries on a long page, every anchor
target present, h2/h3 nesting correct, inline code rendered as a real element,
scroll-margin 80px. Active-section highlighting could NOT be exercised there --
IntersectionObserver does not deliver callbacks in that pane at all, including a
plain observer with no options -- so that path is covered by unit tests rather
than by the browser check.
@loopover-orb

loopover-orb Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Tip

✅ LoopOver review result - approve/merge recommended

Review updated: 2026-07-30 20:13:33 UTC

5 files · 1 AI reviewer · no blockers · readiness 100/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This PR replaces the DOM-scraping/effect-based TOC construction in docs-toc.tsx with a version sourced from the compiled MDX toc, moving the last remaining `react-hooks/set-state-in-effect` site to `error`. The design correctly separates presentational `DocsToc` (pure render) from `DocsTocFromMdx`/`ResolvedToc` (data acquisition via `useChildMatches` + `docsClientLoader.preload`), and state is now derived on render (`restoreActive`) rather than set from an effect body, which is the actual fix for the lint rule. The rAF polling loop in the observer effect is a reasonable, bounded guard against a suspense-ordering hazard the author admits they couldn't fully verify live, and the test suite drives the component via props rather than DOM mutation, matching the new architecture.

Nits — 6 non-blocking
  • docs-toc.tsx's rAF polling loop (MAX_ATTACH_FRAMES=120) is unverified against the real ordering hazard it targets (author states so directly) — worth a follow-up manual check in a real browser once merged.
  • The magic numbers 120 (MAX_ATTACH_FRAMES) and the depth-3 threshold `heading.level >= 3` are documented in comments but not named constants, which is fine but slightly duplicated across the two `>= 3` occurrences in docs-toc.tsx:129/142.
  • docs-toc.test.tsx does not exercise `DocsTocFromMdx`/`ResolvedToc` (the `use()` + `useChildMatches` wiring) at all — only the pure `DocsToc` is tested, leaving the actual MDX-path integration unverified by this PR's own test file.
  • The eslint.config.ts comment update and docs-page.tsx's scroll-mt-20 CSS swap are both correctly scoped incidental changes tied to this fix, but could be called out more explicitly in the PR description's diff summary.
  • Consider a small test for `DocsTocFromMdx`/`ResolvedToc` mocking `docsClientLoader.preload` and `useChildMatches` to cover the path-resolution and toc-mapping logic (docs-toc.tsx:161-180), since that's the actual new integration surface introduced here.
  • PR author also opened the linked issue — Link an issue that was opened by a different contributor, or provide a rationale for why this self-authored issue represents genuine discovery work.

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #9872
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 9 registered-repo PR(s), 8 merged, 280 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 9 PR(s), 280 issue(s).
Improvement ✅ Minor risk: clean · value: minor · LLM: significant
Linked issue satisfaction

Addressed
The PR replaces the DOM-scraping DocsToc with a pure component fed compiled MDX toc data via a new DocsTocFromMdx client-loader reader, resolving the layout/child-route split via useChildMatches, and explicitly leaves non-MDX docs pages without a rail as a deliberate opt-out per the issue's acceptance criteria. It also flips react-hooks/set-state-in-effect back to error in eslint.config.ts with th

Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Python, TypeScript, Ruby, Go, MDX, Shell, Solidity, JavaScript
  • Official Gittensor activity: 9 PR(s), 280 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Treat this as maintainer-lane context rather than normal contributor-lane activity.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

Visual preview
Route Viewport Before (production) After (this PR's preview) Diff
/docs desktop before /docs
before /docs
after /docs
after /docs
/docs mobile before /docs (mobile)
before /docs (mobile)
after /docs (mobile)
after /docs (mobile)

Click any thumbnail to open the full-size screenshot. Before = production · After = this PR's preview deploy.

Scroll preview
Route Before (production) After (this PR's preview)
/docs before /docs (scroll)
before /docs (scroll)
after /docs (scroll)
after /docs (scroll)

A short scroll-through clip (desktop) — click either thumbnail to open the full animation. Evidence for scroll-linked behavior a single screenshot can't show.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
loopover-ui c36594a Commit Preview URL

Branch Preview URL
Jul 30 2026, 08:08 PM

@codecov

codecov Bot commented Jul 30, 2026

Copy link
Copy Markdown

Bundle Report

Changes will increase total bundle size by 820 bytes (0.01%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
loopover-ui 7.89MB 820 bytes (0.01%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: loopover-ui

Assets Changed:

Asset Name Size Change Total Size Change (%)
assets/add-scalar-classes-Cf3Nn6w3.js (New) 2.16MB 2.16MB 100.0% 🚀
assets/tanstack-vendor-CArzhjLP.js (New) 955.23kB 955.23kB 100.0% 🚀
assets/docs.fumadocs-spike-api-reference-Be8AWFqf.js (New) 443.45kB 443.45kB 100.0% 🚀
assets/AgentScalarChatInterface.vue-i7eu_zSl.js (New) 201.69kB 201.69kB 100.0% 🚀
assets/modal-DxObGOeQ.js (New) 184.5kB 184.5kB 100.0% 🚀
assets/client-CHpvhBzS.js (New) 151.47kB 151.47kB 100.0% 🚀
assets/styles-CGmjney1.css (New) 130.18kB 130.18kB 100.0% 🚀
assets/maintainer-panel-BitOO5AK.js (New) 78.97kB 78.97kB 100.0% 🚀
assets/routes-Dm_KJKg0.js (New) 35.88kB 35.88kB 100.0% 🚀
assets/owner-panel-xTdm1oxd.js (New) 28.26kB 28.26kB 100.0% 🚀
assets/app-CzQiyE11.js (New) 25.82kB 25.82kB 100.0% 🚀
assets/ui-vendor-CopOe5Wm.js (New) 24.57kB 24.57kB 100.0% 🚀
assets/fairness-Dz5JNgdL.js (New) 23.13kB 23.13kB 100.0% 🚀
assets/miner-panel-kBqAuSBh.js (New) 20.49kB 20.49kB 100.0% 🚀
assets/api._op-BPYGt70c.js (New) 17.51kB 17.51kB 100.0% 🚀
assets/self-hosting-docs-audit-BSCKW7_b.js (New) 16.6kB 16.6kB 100.0% 🚀
assets/docs-client-loader-BWG28Ey1.js (New) 15.51kB 15.51kB 100.0% 🚀
assets/playground-panel-DXFnOyb1.js (New) 14.35kB 14.35kB 100.0% 🚀
assets/app.audit-CjrFcal4.js (New) 10.22kB 10.22kB 100.0% 🚀
assets/app.config-generator-BNCfh0SX.js (New) 10.06kB 10.06kB 100.0% 🚀
assets/maintainers-B9m6eBK4.js (New) 8.06kB 8.06kB 100.0% 🚀
assets/miners-DHZuQnUp.js (New) 7.91kB 7.91kB 100.0% 🚀
assets/agents-DMl_7rOa.js (New) 7.74kB 7.74kB 100.0% 🚀
assets/commands-panel-gkRVSDbB.js (New) 6.74kB 6.74kB 100.0% 🚀
assets/maintainer-workflow-oRMyL0kw.js (New) 6.52kB 6.52kB 100.0% 🚀
assets/digest-panel-isbmABv4.js (New) 6.15kB 6.15kB 100.0% 🚀
assets/repos._owner._repo.quality-BVn025bU.js (New) 6.14kB 6.14kB 100.0% 🚀
assets/docs-nav-BGT7NsFf.js (New) 6.12kB 6.12kB 100.0% 🚀
assets/docs.index-Cnv1ZkB9.js (New) 6.01kB 6.01kB 100.0% 🚀
assets/api.index-BAm3MzNN.js (New) 4.7kB 4.7kB 100.0% 🚀
assets/docs-CCmQgG5I.js (New) 3.01kB 3.01kB 100.0% 🚀
assets/api-Cfxr3LTM.js (New) 2.66kB 2.66kB 100.0% 🚀
assets/docs-page-CNTFeRd6.js (New) 2.14kB 2.14kB 100.0% 🚀
assets/table-BSKrevt2.js (New) 1.75kB 1.75kB 100.0% 🚀
assets/app.workbench-CJ8Jx7vz.js (New) 1.58kB 1.58kB 100.0% 🚀
assets/tabs-CUPaw-wH.js (New) 1.39kB 1.39kB 100.0% 🚀
assets/app.repos-CzU5qUPb.js (New) 1.07kB 1.07kB 100.0% 🚀
assets/input-Camc98xc.js (New) 796 bytes 796 bytes 100.0% 🚀
assets/file-cog-DMwhJ6Nw.js (New) 758 bytes 758 bytes 100.0% 🚀
assets/docs._slug-DPOLwPoi.js (New) 549 bytes 549 bytes 100.0% 🚀
assets/app.maintainer-C1YxcfXb.js (New) 502 bytes 502 bytes 100.0% 🚀
assets/app.owner-BslY6Q5g.js (New) 474 bytes 474 bytes 100.0% 🚀
assets/app.commands-BoaA-NUX.js (New) 455 bytes 455 bytes 100.0% 🚀
assets/app.playground-B1zP7ODP.js (New) 442 bytes 442 bytes 100.0% 🚀
assets/index-BN0xmUfP.js (New) 438 bytes 438 bytes 100.0% 🚀
assets/app.digest-Bo0fiVHZ.js (New) 430 bytes 430 bytes 100.0% 🚀
assets/eye-off-ESv1fUkZ.js (New) 430 bytes 430 bytes 100.0% 🚀
assets/app.miner-Dmw80Mx9.js (New) 422 bytes 422 bytes 100.0% 🚀
assets/key-round-CIAIFC6e.js (New) 355 bytes 355 bytes 100.0% 🚀
assets/bot-COadFKWP.js (New) 328 bytes 328 bytes 100.0% 🚀
assets/git-pull-request-arrow-DTawd7rT.js (New) 321 bytes 321 bytes 100.0% 🚀
assets/list-checks-IGJiaKKs.js (New) 279 bytes 279 bytes 100.0% 🚀
assets/compass-DuACOrh5.js (New) 251 bytes 251 bytes 100.0% 🚀
assets/history-D2CbX1zC.js (New) 237 bytes 237 bytes 100.0% 🚀
assets/message-square-D4EOLc35.js (New) 233 bytes 233 bytes 100.0% 🚀
assets/lock-KJDdYeAS.js (New) 206 bytes 206 bytes 100.0% 🚀
assets/play-GGEK4eeQ.js (New) 190 bytes 190 bytes 100.0% 🚀
assets/circle-check-DCdbT6qO.js (New) 178 bytes 178 bytes 100.0% 🚀
assets/add-scalar-classes-DMlF-xzR.js (Deleted) -2.16MB 0 bytes -100.0% 🗑️
assets/tanstack-vendor-Bz5TP_nH.js (Deleted) -954.94kB 0 bytes -100.0% 🗑️
assets/docs.fumadocs-spike-api-reference-Dzae_1zD.js (Deleted) -443.45kB 0 bytes -100.0% 🗑️
assets/AgentScalarChatInterface.vue-BlhRZBpU.js (Deleted) -201.69kB 0 bytes -100.0% 🗑️
assets/modal-CAqT9SKU.js (Deleted) -184.5kB 0 bytes -100.0% 🗑️
assets/client-DYxNuTM5.js (Deleted) -151.47kB 0 bytes -100.0% 🗑️
assets/styles-DumG2bhJ.css (Deleted) -130.03kB 0 bytes -100.0% 🗑️
assets/maintainer-panel-BPo6_2id.js (Deleted) -78.97kB 0 bytes -100.0% 🗑️
assets/routes-XDNJ4d5U.js (Deleted) -35.88kB 0 bytes -100.0% 🗑️
assets/owner-panel-BnEvWD6T.js (Deleted) -28.26kB 0 bytes -100.0% 🗑️
assets/app-CbyyeQdD.js (Deleted) -25.82kB 0 bytes -100.0% 🗑️
assets/ui-vendor-C5dv2qmi.js (Deleted) -24.57kB 0 bytes -100.0% 🗑️
assets/fairness-B8I43C2Q.js (Deleted) -23.13kB 0 bytes -100.0% 🗑️
assets/miner-panel-DH7TukIf.js (Deleted) -20.49kB 0 bytes -100.0% 🗑️
assets/api._op-Vv34b0Vz.js (Deleted) -17.51kB 0 bytes -100.0% 🗑️
assets/self-hosting-docs-audit-DwWgAOC9.js (Deleted) -16.6kB 0 bytes -100.0% 🗑️
assets/docs._slug-DSCrxTdo.js (Deleted) -15.79kB 0 bytes -100.0% 🗑️
assets/playground-panel-DfTjEWhx.js (Deleted) -14.35kB 0 bytes -100.0% 🗑️
assets/app.audit-dvZ6eVAr.js (Deleted) -10.22kB 0 bytes -100.0% 🗑️
assets/app.config-generator-BW9xjbkS.js (Deleted) -10.06kB 0 bytes -100.0% 🗑️
assets/maintainers-C154Dg62.js (Deleted) -8.06kB 0 bytes -100.0% 🗑️
assets/miners-B9TBwWn6.js (Deleted) -7.91kB 0 bytes -100.0% 🗑️
assets/agents-D6gXEih8.js (Deleted) -7.74kB 0 bytes -100.0% 🗑️
assets/commands-panel-DNO-04pg.js (Deleted) -6.74kB 0 bytes -100.0% 🗑️
assets/maintainer-workflow-BgqucogK.js (Deleted) -6.52kB 0 bytes -100.0% 🗑️
assets/digest-panel-CK8221Wu.js (Deleted) -6.15kB 0 bytes -100.0% 🗑️
assets/repos._owner._repo.quality-CO5USSX5.js (Deleted) -6.14kB 0 bytes -100.0% 🗑️
assets/docs-nav-DOLNMja2.js (Deleted) -6.12kB 0 bytes -100.0% 🗑️
assets/docs.index-DnytQy_3.js (Deleted) -6.01kB 0 bytes -100.0% 🗑️
assets/api.index-Cavcgun6.js (Deleted) -4.7kB 0 bytes -100.0% 🗑️
assets/docs-BCqadd7B.js (Deleted) -2.93kB 0 bytes -100.0% 🗑️
assets/api-SRxXedXg.js (Deleted) -2.66kB 0 bytes -100.0% 🗑️
assets/docs-page-C_iIMCit.js (Deleted) -2.1kB 0 bytes -100.0% 🗑️
assets/table-JCg3Zv-g.js (Deleted) -1.75kB 0 bytes -100.0% 🗑️
assets/app.workbench-v0EXn0KS.js (Deleted) -1.58kB 0 bytes -100.0% 🗑️
assets/tabs-DU3sKib8.js (Deleted) -1.39kB 0 bytes -100.0% 🗑️
assets/app.repos-BDtyai81.js (Deleted) -1.07kB 0 bytes -100.0% 🗑️
assets/input-D2S548WP.js (Deleted) -796 bytes 0 bytes -100.0% 🗑️
assets/file-cog-D2zTO_Tf.js (Deleted) -758 bytes 0 bytes -100.0% 🗑️
assets/app.maintainer-CHL0HCi6.js (Deleted) -502 bytes 0 bytes -100.0% 🗑️
assets/app.owner-BrgLLrPD.js (Deleted) -474 bytes 0 bytes -100.0% 🗑️
assets/app.commands-Iua-OB34.js (Deleted) -455 bytes 0 bytes -100.0% 🗑️
assets/app.playground-BjnSgpyn.js (Deleted) -442 bytes 0 bytes -100.0% 🗑️
assets/index-B-AHviKB.js (Deleted) -438 bytes 0 bytes -100.0% 🗑️
assets/app.digest-YUeIOzgF.js (Deleted) -430 bytes 0 bytes -100.0% 🗑️
assets/eye-off-CU-prEao.js (Deleted) -430 bytes 0 bytes -100.0% 🗑️
assets/app.miner-DZ8gh1UE.js (Deleted) -422 bytes 0 bytes -100.0% 🗑️
assets/key-round-C8rQrt5C.js (Deleted) -355 bytes 0 bytes -100.0% 🗑️
assets/bot-Dho_h2q2.js (Deleted) -328 bytes 0 bytes -100.0% 🗑️
assets/git-pull-request-arrow-5FUqIkB-.js (Deleted) -321 bytes 0 bytes -100.0% 🗑️
assets/list-checks-BdG3CHpQ.js (Deleted) -279 bytes 0 bytes -100.0% 🗑️
assets/compass-BwLHZD_F.js (Deleted) -251 bytes 0 bytes -100.0% 🗑️
assets/history-rm-Bs7bW.js (Deleted) -237 bytes 0 bytes -100.0% 🗑️
assets/message-square-CI-0SyW5.js (Deleted) -233 bytes 0 bytes -100.0% 🗑️
assets/lock-D637wguW.js (Deleted) -206 bytes 0 bytes -100.0% 🗑️
assets/play--1bI_PuV.js (Deleted) -190 bytes 0 bytes -100.0% 🗑️
assets/circle-check-pRBO7927.js (Deleted) -178 bytes 0 bytes -100.0% 🗑️

@loopover-orb loopover-orb Bot 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.

LoopOver approves — the gate is satisfied and CI is green.

@loopover-orb
loopover-orb Bot merged commit c133f01 into main Jul 30, 2026
10 checks passed
@loopover-orb
loopover-orb Bot deleted the fix/docs-toc-from-mdx-9872 branch July 30, 2026 20:13
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.

ui(docs): source the docs TOC from the compiled MDX toc instead of scraping the rendered DOM

1 participant