fix(ui): stop docs-source's fumadocs-mdx lookup from crashing client-side nav#7632
Conversation
…side nav Every docs.*.tsx route's loader imported docs-source.ts (fumadocs-mdx's generated collections/server module) directly. TanStack Router route loaders run in the browser on client-side navigations, not just the server, so the Node-only lookup (path.join) crashed every doc page when reached by an in-app click -- direct hard loads were unaffected, which made this easy to miss. Move the lookup behind a createServerFn (docs-source.functions.ts), matching the existing .server.ts + createServerFn pattern in this codebase, so it always runs server-side and the client fetches the result over the wire instead of re-executing the module in the browser. Updated all 48 docs.*.tsx route loaders. Closes #7631
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
loopover-ui | 1ed9611 | Commit Preview URL Branch Preview URL |
Jul 21 2026, 05:10 AM |
Bundle ReportChanges will decrease total bundle size by 238.25kB (-3.11%) ⬇️. This is within the configured threshold ✅ Detailed changes
Affected Assets, Files, and Routes:view changes for bundle: loopover-uiAssets Changed:
|
|
Tip ✅ LoopOver review result - approve/merge recommendedReview updated: 2026-07-21 05:14:51 UTC
Review summary Nits — 5 non-blocking
Decision drivers
Context & advisory signals — never blocks the verdict
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk 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.
Full command reference: https://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. Visual previewClick any thumbnail to open the full-size screenshot. Before = production · After = this PR's preview deploy. Scroll previewA 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.
|




Summary
/docs/*pages inapps/loopover-uicrashed with a full "This page didn't load" error screen when reached via normal in-app navigation (clicking a link). Direct hard page loads were unaffected, which made this easy to miss during review — confirmed reproducing on the liveloopover.aisite.apps/loopover-ui/src/lib/docs-source.tsimportedcollections/server, fumadocs-mdx's generated, filesystem-backed runtime module (globs everycontent/docs/*.mdxfile, depends on Node'spath). Everydocs.*.tsxroute'sloader()imported it directly viaawait import("@/lib/docs-source"). TanStack Router route loaders run both on the server (SSR/hard loads) and in the browser (client-side/SPA navigations) — so on a soft navigation this server-only module executed in the browser, wherepath.joindoesn't exist, throwingTypeError: D.join is not a functionand rendering the router's error boundary.5003fabe6, 2026-07-16) — docs pages were hand-authored JSX components before that and never hit this path.createServerFn(docs-source.functions.ts+docs-source.server.ts), matching this codebase's existing.server.ts+createServerFnpattern (config.server.ts+example.functions.ts). The client now fetches the page metadata over the wire instead of re-executing the Node-only fumadocs-mdx module in the browser. Updated all 48docs.*.tsxroute loaders to callgetDocPage(...)instead of importingdocs-sourcedirectly.docs-source.serverimport inside the server function is a dynamicawait import(...)(not a static top-level import) — a static import would drag the eagercontent/docs/*.mdxglob into any test that merely imports a route module without invoking its loader (caught this viadocs.miner-coding-agent.test.tsx, sincevitest.config.tsdoesn't register the fumadocs-mdx plugin needed to parse.mdxfiles).Scope
type(scope): short summaryConventional Commit format.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run actionlint(vianpm run test:ci)npm run typecheck(vianpm run test:ci)npm run test:coveragelocally — full suite green (1036+ files, 19500+ tests); this is a UI-only change underapps/loopover-ui/**, which Codecov'scodecov/patchdoes not measure (onlysrc/**is measured), so there's no patch-coverage obligation — added a structural regression test anyway (docs-source-server-isolation.test.ts) guarding that all 48 in-scope routes go throughgetDocPage, notdocs-source(.server)directly.npm run test:workers(vianpm run test:ci)npm run build:mcp/npm run test:mcp-pack(vianpm run test:ci)npm run ui:openapi:check(vianpm run test:ci) — no API/schema changes, N/A but ran cleannpm run ui:lintnpm run ui:typechecknpm run ui:build— also verified the built client bundle no longer contains anydocs-sourcechunk or reference tocollections/server/fumadocs-mdx/runtime/server(confirmed viagrepoverdist/client/assets)npm audit --audit-level=moderate— 0 vulnerabilitiesdocs-source-server-isolation.test.tsas a drift guard.Manual verification: served a production build (
vite build, thenwrangler dev --config dist/server/wrangler.jsonagainst the built Worker output —vite previewitself has an unrelated, pre-existing breakage in this repo, filed separately) and clicked through multiple docs pages via in-app navigation (Docs → Quickstart, sidebar → other pages) — zero console errors, pages render correctly, matching the pre-fix reproduction exactly but now fixed. Confirmed the crash reproduced identically on unmodifiedmainbefore this fix (stashed the change, same click-through, samepath.join is not a functioncrash).Safety
UI Evidencesection — not applicable: this produces zero pixel/visual difference on a successful load (the page content is identical); the only observable difference is that the page loads at all on SPA navigation instead of crashing. See Notes for the actual before/after evidence (console error + error screen vs. clean render).Notes
Before (reproduced on unmodified
main, clicking Docs → any doc page from the homepage): the page rendered a full "This page didn't load / Something went wrong on our end" error screen, withTypeError: D.join is not a functionin the console, originating from fumadocs-mdx'sdoc()/docs()functions in thedocs-sourcebundle.After: the same click-through renders the target doc page normally, with an empty console (aside from an unrelated pre-existing
VITE_LOOPOVER_API_ORIGINinfo warning).