From 1ed9611f21eacf6ba4494f449b8ee60f468d8d69 Mon Sep 17 00:00:00 2001 From: JSONbored <49853598+JSONbored@users.noreply.github.com> Date: Mon, 20 Jul 2026 22:07:26 -0700 Subject: [PATCH] fix(ui): stop docs-source's fumadocs-mdx lookup from crashing client-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 --- .../lib/docs-source-server-isolation.test.ts | 49 +++++++++++++++++++ .../src/lib/docs-source.functions.ts | 22 +++++++++ .../loopover-ui/src/lib/docs-source.server.ts | 21 ++++++++ apps/loopover-ui/src/lib/docs-source.ts | 7 --- .../src/routes/docs-mdx-eager-scope.test.ts | 2 +- .../src/routes/docs.ai-summaries.tsx | 8 +-- .../src/routes/docs.ams-config-precedence.tsx | 8 +-- .../src/routes/docs.ams-deployment.tsx | 8 +-- .../src/routes/docs.ams-discovery-plane.tsx | 8 +-- .../src/routes/docs.ams-env-reference.tsx | 8 +-- .../src/routes/docs.ams-fleet-manifest.tsx | 8 +-- .../src/routes/docs.ams-goal-spec.tsx | 8 +-- .../routes/docs.ams-kill-switch-incident.tsx | 8 +-- .../docs.ams-observability-callout.test.tsx | 5 +- .../src/routes/docs.ams-observability.tsx | 8 +-- .../routes/docs.ams-operations-runbook.tsx | 8 +-- .../src/routes/docs.ams-sizing.tsx | 8 +-- .../routes/docs.ams-unattended-scheduling.tsx | 8 +-- .../src/routes/docs.beta-onboarding.tsx | 8 +-- .../src/routes/docs.branch-analysis.tsx | 8 +-- apps/loopover-ui/src/routes/docs.capacity.tsx | 8 +-- .../docs.federated-fleet-intelligence.tsx | 8 +-- .../src/routes/docs.github-app.tsx | 8 +-- .../src/routes/docs.how-reviews-work.tsx | 8 +-- .../src/routes/docs.loopover-commands.tsx | 8 +-- .../routes/docs.maintainer-install-trust.tsx | 8 +-- .../routes/docs.maintainer-self-hosting.tsx | 8 +-- .../src/routes/docs.maintainer-workflow.tsx | 8 +-- .../src/routes/docs.mcp-clients.tsx | 8 +-- .../routes/docs.miner-coding-agent.test.tsx | 2 +- .../src/routes/docs.miner-coding-agent.tsx | 8 +-- .../src/routes/docs.miner-quickstart.tsx | 8 +-- .../src/routes/docs.miner-workflow.tsx | 8 +-- .../src/routes/docs.owner-checklist.tsx | 8 +-- .../src/routes/docs.privacy-security.tsx | 8 +-- .../src/routes/docs.quickstart.tsx | 8 +-- .../src/routes/docs.scoreability.tsx | 8 +-- .../routes/docs.self-hosting-ai-providers.tsx | 8 +-- .../docs.self-hosting-backup-scaling.tsx | 8 +-- .../docs.self-hosting-configuration.tsx | 8 +-- .../routes/docs.self-hosting-docs-audit.tsx | 8 +-- .../routes/docs.self-hosting-github-app.tsx | 8 +-- .../routes/docs.self-hosting-operations.tsx | 8 +-- .../routes/docs.self-hosting-quickstart.tsx | 8 +-- .../src/routes/docs.self-hosting-rag.tsx | 8 +-- .../docs.self-hosting-rees-analyzers.tsx | 8 +-- .../src/routes/docs.self-hosting-rees.tsx | 8 +-- .../docs.self-hosting-release-checklist.tsx | 8 +-- .../src/routes/docs.self-hosting-releases.tsx | 8 +-- .../src/routes/docs.self-hosting-security.tsx | 8 +-- .../docs.self-hosting-troubleshooting.tsx | 8 +-- .../docs.self-hosting-unified-ams-orb.tsx | 8 +-- .../src/routes/docs.troubleshooting.tsx | 8 +-- apps/loopover-ui/src/routes/docs.tuning.tsx | 8 +-- .../src/routes/docs.upstream-drift.tsx | 8 +-- 55 files changed, 289 insertions(+), 203 deletions(-) create mode 100644 apps/loopover-ui/src/lib/docs-source-server-isolation.test.ts create mode 100644 apps/loopover-ui/src/lib/docs-source.functions.ts create mode 100644 apps/loopover-ui/src/lib/docs-source.server.ts delete mode 100644 apps/loopover-ui/src/lib/docs-source.ts diff --git a/apps/loopover-ui/src/lib/docs-source-server-isolation.test.ts b/apps/loopover-ui/src/lib/docs-source-server-isolation.test.ts new file mode 100644 index 0000000000..d45b00e2e0 --- /dev/null +++ b/apps/loopover-ui/src/lib/docs-source-server-isolation.test.ts @@ -0,0 +1,49 @@ +import { readFileSync, readdirSync } from "node:fs"; +import { join } from "node:path"; +import { describe, expect, it } from "vitest"; + +// REGRESSION: docs-source.ts (now docs-source.server.ts) imports fumadocs-mdx's generated +// `collections/server` module, which globs every content/docs/*.mdx file eagerly and depends +// on Node's `path` module. Every docs.*.tsx route's loader used to import it directly -- +// TanStack Router route loaders run in the browser on client-side navigations, not just on +// the server, so any in-app click into a docs page (not a hard reload) crashed with +// "path.join is not a function" and rendered the router's error boundary. Fixed by moving the +// fumadocs-mdx lookup behind a createServerFn (docs-source.functions.ts) so the client always +// fetches the result over the wire instead of re-executing the server-only module itself. +// +// docs-source.server.ts isn't imported here: like docs.miner-coding-agent.test.tsx and +// docs.ams-observability-callout.test.tsx, actually evaluating fumadocs-mdx's generated +// `collections/server` module needs the fumadocs-mdx Vite plugin (registered for the app build, +// not this standalone vitest.config.ts), so this is a source-level drift guard instead. + +describe("docs.*.tsx routes never import docs-source(.server) directly", () => { + const routesDir = join(process.cwd(), "src/routes"); + const outOfScope = new Set([ + "docs.fumadocs-spike-api-reference.tsx", + "docs.index.tsx", + "docs.tsx", + ]); + const docsRouteFiles = readdirSync(routesDir).filter( + (name) => name.startsWith("docs.") && name.endsWith(".tsx") && !name.endsWith(".test.tsx"), + ); + const inScope = docsRouteFiles.filter((name) => !outOfScope.has(name)); + + it("found the expected set of in-scope docs route files", () => { + expect(inScope.length).toBe(48); + }); + + it.each(inScope)( + "%s: loads doc metadata via getDocPage, not docs-source.server directly", + (file) => { + const source = readFileSync(join(routesDir, file), "utf8"); + expect(source, `${file} should import getDocPage from docs-source.functions`).toContain( + 'import { getDocPage } from "@/lib/docs-source.functions";', + ); + expect( + source, + `${file} must not import docs-source(.server) directly -- it would ship the ` + + "Node-only fumadocs-mdx lookup into the client bundle and crash on SPA navigation", + ).not.toMatch(/from ["']@\/lib\/docs-source(\.server)?["']/); + }, + ); +}); diff --git a/apps/loopover-ui/src/lib/docs-source.functions.ts b/apps/loopover-ui/src/lib/docs-source.functions.ts new file mode 100644 index 0000000000..abdfe86d8f --- /dev/null +++ b/apps/loopover-ui/src/lib/docs-source.functions.ts @@ -0,0 +1,22 @@ +import { createServerFn } from "@tanstack/react-start"; +import { z } from "zod"; + +// Server function wrapper around docs-source.server.ts's fumadocs-mdx lookup. Every +// docs.*.tsx route loader calls this instead of importing docs-source.server directly -- +// see that file's comment for why. Going through createServerFn keeps the lookup +// server-only on both hard loads and client-side navigations: the client calls this over +// the wire instead of re-executing docs-source.server.ts (and its Node-only dependencies) +// in the browser. +// +// The import of docs-source.server is dynamic (inside the handler) rather than a static +// top-level import: this file itself is a static import in every docs.*.tsx route, and a +// static top-level import here would drag docs-source.server.ts's eager content/docs/*.mdx +// glob into any test that merely imports a docs.*.tsx route module without invoking its +// loader (e.g. docs.miner-coding-agent.test.tsx importing named exports for assertions) -- +// vitest.config.ts doesn't register the fumadocs-mdx plugin needed to parse those files. +export const getDocPage = createServerFn({ method: "POST" }) + .inputValidator(z.object({ slugs: z.array(z.string()) })) + .handler(async ({ data }) => { + const { getDocPageMeta } = await import("./docs-source.server"); + return getDocPageMeta(data.slugs); + }); diff --git a/apps/loopover-ui/src/lib/docs-source.server.ts b/apps/loopover-ui/src/lib/docs-source.server.ts new file mode 100644 index 0000000000..feb4bbd86b --- /dev/null +++ b/apps/loopover-ui/src/lib/docs-source.server.ts @@ -0,0 +1,21 @@ +import { docs } from "collections/server"; +import { loader } from "fumadocs-core/source"; + +// Server-only (the .server.ts suffix keeps this out of the client bundle, see +// config.server.ts). `collections/server` is fumadocs-mdx's generated, filesystem-backed +// runtime -- it globs every content/docs/*.mdx file eagerly and depends on Node's `path` +// module, which doesn't exist in the browser. TanStack Router route loaders run on both +// the server (hard loads) AND in the browser (client-side navigations), so this module +// must never be imported directly from a route loader -- only through getDocPageMeta() +// below, called via the createServerFn in docs-source.functions.ts, so a client-side +// navigation fetches the result over the wire instead of re-executing this module. +export const docsSource = loader({ + baseUrl: "/docs", + source: docs.toFumadocsSource(), +}); + +export function getDocPageMeta(slugs: string[]) { + const page = docsSource.getPage(slugs); + if (!page) return null; + return { path: page.path, title: page.data.title, description: page.data.description }; +} diff --git a/apps/loopover-ui/src/lib/docs-source.ts b/apps/loopover-ui/src/lib/docs-source.ts deleted file mode 100644 index c80dcc8d44..0000000000 --- a/apps/loopover-ui/src/lib/docs-source.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { docs } from "collections/server"; -import { loader } from "fumadocs-core/source"; - -export const docsSource = loader({ - baseUrl: "/docs", - source: docs.toFumadocsSource(), -}); diff --git a/apps/loopover-ui/src/routes/docs-mdx-eager-scope.test.ts b/apps/loopover-ui/src/routes/docs-mdx-eager-scope.test.ts index bb326f6544..3abb946313 100644 --- a/apps/loopover-ui/src/routes/docs-mdx-eager-scope.test.ts +++ b/apps/loopover-ui/src/routes/docs-mdx-eager-scope.test.ts @@ -12,7 +12,7 @@ import { docsMdxComponents } from "@/lib/docs-mdx-components"; // unimported provided-component name there is a bare, unresolved identifier: a raw ReferenceError, // not fumadocs' friendly message. // -// That alone would only break the one page. It broke every docs page because docs-source.ts (used by +// That alone would only break the one page. It broke every docs page because docs-source.server.ts (used by // every docs.*.tsx route's server loader) imports fumadocs-mdx's generated collections/server module, // which globs *all* content/docs/*.mdx files with `eager: true` -- so one file with this defect throws // during module evaluation and takes down every docs route's SSR loader, not just its own page. diff --git a/apps/loopover-ui/src/routes/docs.ai-summaries.tsx b/apps/loopover-ui/src/routes/docs.ai-summaries.tsx index b5987d8a51..fd1e6f42bb 100644 --- a/apps/loopover-ui/src/routes/docs.ai-summaries.tsx +++ b/apps/loopover-ui/src/routes/docs.ai-summaries.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/ai-summaries.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/ai-summaries")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["ai-summaries"]); + const page = await getDocPage({ data: { slugs: ["ai-summaries"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.ams-config-precedence.tsx b/apps/loopover-ui/src/routes/docs.ams-config-precedence.tsx index 44b16ab4d5..423ab27d41 100644 --- a/apps/loopover-ui/src/routes/docs.ams-config-precedence.tsx +++ b/apps/loopover-ui/src/routes/docs.ams-config-precedence.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/ams-config-precedence.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/ams-config-precedence")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["ams-config-precedence"]); + const page = await getDocPage({ data: { slugs: ["ams-config-precedence"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.ams-deployment.tsx b/apps/loopover-ui/src/routes/docs.ams-deployment.tsx index 9428ca4bed..3ad1815922 100644 --- a/apps/loopover-ui/src/routes/docs.ams-deployment.tsx +++ b/apps/loopover-ui/src/routes/docs.ams-deployment.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/ams-deployment.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/ams-deployment")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["ams-deployment"]); + const page = await getDocPage({ data: { slugs: ["ams-deployment"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.ams-discovery-plane.tsx b/apps/loopover-ui/src/routes/docs.ams-discovery-plane.tsx index dc8b37d75c..892d5c9959 100644 --- a/apps/loopover-ui/src/routes/docs.ams-discovery-plane.tsx +++ b/apps/loopover-ui/src/routes/docs.ams-discovery-plane.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/ams-discovery-plane.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/ams-discovery-plane")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["ams-discovery-plane"]); + const page = await getDocPage({ data: { slugs: ["ams-discovery-plane"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.ams-env-reference.tsx b/apps/loopover-ui/src/routes/docs.ams-env-reference.tsx index dfbec9057a..b7d3d69f92 100644 --- a/apps/loopover-ui/src/routes/docs.ams-env-reference.tsx +++ b/apps/loopover-ui/src/routes/docs.ams-env-reference.tsx @@ -4,10 +4,11 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/ams-env-reference.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock primitives -- -// not fumadocs-ui's bundled components. See docs-source.ts's comment for why the +// not fumadocs-ui's bundled components. See docs-source.server.ts's comment for why the // loader below resolves only a plain, serializable path string. The .mdx content // itself imports AMS_ENV_REFERENCE_MARKDOWN from @/lib/ams-env-reference (generated by // packages/loopover-miner/scripts/generate-env-reference.mjs, drift-checked in CI), @@ -15,10 +16,9 @@ import { docsClientLoader } from "@/lib/docs-client-loader"; // SELFHOST_ENV_REFERENCE_MARKDOWN. export const Route = createFileRoute("/docs/ams-env-reference")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["ams-env-reference"]); + const page = await getDocPage({ data: { slugs: ["ams-env-reference"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.ams-fleet-manifest.tsx b/apps/loopover-ui/src/routes/docs.ams-fleet-manifest.tsx index a8ce6ae245..49d5c9c4cd 100644 --- a/apps/loopover-ui/src/routes/docs.ams-fleet-manifest.tsx +++ b/apps/loopover-ui/src/routes/docs.ams-fleet-manifest.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/ams-fleet-manifest.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/ams-fleet-manifest")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["ams-fleet-manifest"]); + const page = await getDocPage({ data: { slugs: ["ams-fleet-manifest"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.ams-goal-spec.tsx b/apps/loopover-ui/src/routes/docs.ams-goal-spec.tsx index 23c36373b5..1a8ecfbec9 100644 --- a/apps/loopover-ui/src/routes/docs.ams-goal-spec.tsx +++ b/apps/loopover-ui/src/routes/docs.ams-goal-spec.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/ams-goal-spec.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/ams-goal-spec")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["ams-goal-spec"]); + const page = await getDocPage({ data: { slugs: ["ams-goal-spec"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.ams-kill-switch-incident.tsx b/apps/loopover-ui/src/routes/docs.ams-kill-switch-incident.tsx index 96fb0786af..eebc018cae 100644 --- a/apps/loopover-ui/src/routes/docs.ams-kill-switch-incident.tsx +++ b/apps/loopover-ui/src/routes/docs.ams-kill-switch-incident.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/ams-kill-switch-incident.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/ams-kill-switch-incident")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["ams-kill-switch-incident"]); + const page = await getDocPage({ data: { slugs: ["ams-kill-switch-incident"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.ams-observability-callout.test.tsx b/apps/loopover-ui/src/routes/docs.ams-observability-callout.test.tsx index 9175e191f3..37d0803de0 100644 --- a/apps/loopover-ui/src/routes/docs.ams-observability-callout.test.tsx +++ b/apps/loopover-ui/src/routes/docs.ams-observability-callout.test.tsx @@ -13,8 +13,9 @@ import { } from "../components/site/ams-observability-callout"; // Every route that embeds the shared callout, so a new route add/remove can't silently skip one (#5191). -// These routes render from content/docs/*.mdx via the fumadocs client-loader (see docs-source.ts's -// comment), so this is now a content drift-guard -- checking the .mdx source for the JSX tag -- rather +// These routes render from content/docs/*.mdx via the fumadocs client-loader (see +// docs-source.server.ts's comment), so this is now a content drift-guard -- checking the .mdx source +// for the JSX tag -- rather // than a component render, matching the pattern in docs-selfhost-activation-paths.test.ts. const ROUTES_WITH_CALLOUT = [ ["/docs/self-hosting-operations", "content/docs/self-hosting-operations.mdx"], diff --git a/apps/loopover-ui/src/routes/docs.ams-observability.tsx b/apps/loopover-ui/src/routes/docs.ams-observability.tsx index 69aebee45c..708610118a 100644 --- a/apps/loopover-ui/src/routes/docs.ams-observability.tsx +++ b/apps/loopover-ui/src/routes/docs.ams-observability.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/ams-observability.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/ams-observability")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["ams-observability"]); + const page = await getDocPage({ data: { slugs: ["ams-observability"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.ams-operations-runbook.tsx b/apps/loopover-ui/src/routes/docs.ams-operations-runbook.tsx index 0f3a1e6d6f..afc981a334 100644 --- a/apps/loopover-ui/src/routes/docs.ams-operations-runbook.tsx +++ b/apps/loopover-ui/src/routes/docs.ams-operations-runbook.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/ams-operations-runbook.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/ams-operations-runbook")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["ams-operations-runbook"]); + const page = await getDocPage({ data: { slugs: ["ams-operations-runbook"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.ams-sizing.tsx b/apps/loopover-ui/src/routes/docs.ams-sizing.tsx index 6fe334f4fc..650863582a 100644 --- a/apps/loopover-ui/src/routes/docs.ams-sizing.tsx +++ b/apps/loopover-ui/src/routes/docs.ams-sizing.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/ams-sizing.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/ams-sizing")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["ams-sizing"]); + const page = await getDocPage({ data: { slugs: ["ams-sizing"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.ams-unattended-scheduling.tsx b/apps/loopover-ui/src/routes/docs.ams-unattended-scheduling.tsx index b86c3818e3..0fdabeb76f 100644 --- a/apps/loopover-ui/src/routes/docs.ams-unattended-scheduling.tsx +++ b/apps/loopover-ui/src/routes/docs.ams-unattended-scheduling.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/ams-unattended-scheduling.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/ams-unattended-scheduling")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["ams-unattended-scheduling"]); + const page = await getDocPage({ data: { slugs: ["ams-unattended-scheduling"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.beta-onboarding.tsx b/apps/loopover-ui/src/routes/docs.beta-onboarding.tsx index 1fad6b5ca3..050ba07e17 100644 --- a/apps/loopover-ui/src/routes/docs.beta-onboarding.tsx +++ b/apps/loopover-ui/src/routes/docs.beta-onboarding.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/beta-onboarding.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/beta-onboarding")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["beta-onboarding"]); + const page = await getDocPage({ data: { slugs: ["beta-onboarding"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.branch-analysis.tsx b/apps/loopover-ui/src/routes/docs.branch-analysis.tsx index 22c76fcf83..bfbdd4dfb5 100644 --- a/apps/loopover-ui/src/routes/docs.branch-analysis.tsx +++ b/apps/loopover-ui/src/routes/docs.branch-analysis.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/branch-analysis.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/branch-analysis")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["branch-analysis"]); + const page = await getDocPage({ data: { slugs: ["branch-analysis"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.capacity.tsx b/apps/loopover-ui/src/routes/docs.capacity.tsx index 3a3143fb12..89d5e6986c 100644 --- a/apps/loopover-ui/src/routes/docs.capacity.tsx +++ b/apps/loopover-ui/src/routes/docs.capacity.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/capacity.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/capacity")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["capacity"]); + const page = await getDocPage({ data: { slugs: ["capacity"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.federated-fleet-intelligence.tsx b/apps/loopover-ui/src/routes/docs.federated-fleet-intelligence.tsx index 844f07100f..7460840cc8 100644 --- a/apps/loopover-ui/src/routes/docs.federated-fleet-intelligence.tsx +++ b/apps/loopover-ui/src/routes/docs.federated-fleet-intelligence.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/federated-fleet-intelligence.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/federated-fleet-intelligence")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["federated-fleet-intelligence"]); + const page = await getDocPage({ data: { slugs: ["federated-fleet-intelligence"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.github-app.tsx b/apps/loopover-ui/src/routes/docs.github-app.tsx index fca11e716f..b33b55a742 100644 --- a/apps/loopover-ui/src/routes/docs.github-app.tsx +++ b/apps/loopover-ui/src/routes/docs.github-app.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/github-app.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/github-app")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["github-app"]); + const page = await getDocPage({ data: { slugs: ["github-app"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.how-reviews-work.tsx b/apps/loopover-ui/src/routes/docs.how-reviews-work.tsx index 139910f02e..8e060ed183 100644 --- a/apps/loopover-ui/src/routes/docs.how-reviews-work.tsx +++ b/apps/loopover-ui/src/routes/docs.how-reviews-work.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/how-reviews-work.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock primitives -- -// not fumadocs-ui's bundled components. See docs-source.ts's comment for why the +// not fumadocs-ui's bundled components. See docs-source.server.ts's comment for why the // loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/how-reviews-work")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["how-reviews-work"]); + const page = await getDocPage({ data: { slugs: ["how-reviews-work"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.loopover-commands.tsx b/apps/loopover-ui/src/routes/docs.loopover-commands.tsx index dfdf44b945..fb5d40fde0 100644 --- a/apps/loopover-ui/src/routes/docs.loopover-commands.tsx +++ b/apps/loopover-ui/src/routes/docs.loopover-commands.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/loopover-commands.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/CommandTable -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/loopover-commands")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["loopover-commands"]); + const page = await getDocPage({ data: { slugs: ["loopover-commands"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.maintainer-install-trust.tsx b/apps/loopover-ui/src/routes/docs.maintainer-install-trust.tsx index 2afd6dc1cd..32295e3173 100644 --- a/apps/loopover-ui/src/routes/docs.maintainer-install-trust.tsx +++ b/apps/loopover-ui/src/routes/docs.maintainer-install-trust.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/maintainer-install-trust.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow primitives -- -// not fumadocs-ui's bundled components. See docs-source.ts's comment for why the loader below +// not fumadocs-ui's bundled components. See docs-source.server.ts's comment for why the loader below // resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/maintainer-install-trust")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["maintainer-install-trust"]); + const page = await getDocPage({ data: { slugs: ["maintainer-install-trust"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.maintainer-self-hosting.tsx b/apps/loopover-ui/src/routes/docs.maintainer-self-hosting.tsx index d1f263f42d..3c2884a048 100644 --- a/apps/loopover-ui/src/routes/docs.maintainer-self-hosting.tsx +++ b/apps/loopover-ui/src/routes/docs.maintainer-self-hosting.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/maintainer-self-hosting.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/FeatureRow primitives -- not -// fumadocs-ui's bundled components. See docs-source.ts's comment for why the loader below +// fumadocs-ui's bundled components. See docs-source.server.ts's comment for why the loader below // resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/maintainer-self-hosting")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["maintainer-self-hosting"]); + const page = await getDocPage({ data: { slugs: ["maintainer-self-hosting"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.maintainer-workflow.tsx b/apps/loopover-ui/src/routes/docs.maintainer-workflow.tsx index 8a6e447a40..4e1ed6c2df 100644 --- a/apps/loopover-ui/src/routes/docs.maintainer-workflow.tsx +++ b/apps/loopover-ui/src/routes/docs.maintainer-workflow.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/maintainer-workflow.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/WorkflowMirror -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment for +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment for // why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/maintainer-workflow")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["maintainer-workflow"]); + const page = await getDocPage({ data: { slugs: ["maintainer-workflow"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.mcp-clients.tsx b/apps/loopover-ui/src/routes/docs.mcp-clients.tsx index 2f358f1ea5..735618f4af 100644 --- a/apps/loopover-ui/src/routes/docs.mcp-clients.tsx +++ b/apps/loopover-ui/src/routes/docs.mcp-clients.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/mcp-clients.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/mcp-clients")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["mcp-clients"]); + const page = await getDocPage({ data: { slugs: ["mcp-clients"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.miner-coding-agent.test.tsx b/apps/loopover-ui/src/routes/docs.miner-coding-agent.test.tsx index 85b3121846..8466d4ea29 100644 --- a/apps/loopover-ui/src/routes/docs.miner-coding-agent.test.tsx +++ b/apps/loopover-ui/src/routes/docs.miner-coding-agent.test.tsx @@ -9,7 +9,7 @@ import { } from "./docs.miner-coding-agent"; // Renders from content/docs/miner-coding-agent.mdx via the fumadocs client-loader (see -// docs-source.ts's comment) -- a synchronous component render can't exercise that path +// docs-source.server.ts's comment) -- a synchronous component render can't exercise that path // without a full router context, so this is now a content drift-guard on the .mdx source, // matching the pattern in docs-selfhost-activation-paths.test.ts. const MDX_PATH = "content/docs/miner-coding-agent.mdx"; diff --git a/apps/loopover-ui/src/routes/docs.miner-coding-agent.tsx b/apps/loopover-ui/src/routes/docs.miner-coding-agent.tsx index 4fb325bbc3..b67d8dd195 100644 --- a/apps/loopover-ui/src/routes/docs.miner-coding-agent.tsx +++ b/apps/loopover-ui/src/routes/docs.miner-coding-agent.tsx @@ -4,10 +4,11 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/miner-coding-agent.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. // // The three arrays below no longer feed this page's own JSX -- their prose was @@ -100,10 +101,9 @@ export const MINER_CODING_AGENT_TRUST_ROWS: Array<{ title: string; description: export const Route = createFileRoute("/docs/miner-coding-agent")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["miner-coding-agent"]); + const page = await getDocPage({ data: { slugs: ["miner-coding-agent"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.miner-quickstart.tsx b/apps/loopover-ui/src/routes/docs.miner-quickstart.tsx index 9958c98f68..b07beb178e 100644 --- a/apps/loopover-ui/src/routes/docs.miner-quickstart.tsx +++ b/apps/loopover-ui/src/routes/docs.miner-quickstart.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/miner-quickstart.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/AmsObservabilityCallout -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/miner-quickstart")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["miner-quickstart"]); + const page = await getDocPage({ data: { slugs: ["miner-quickstart"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.miner-workflow.tsx b/apps/loopover-ui/src/routes/docs.miner-workflow.tsx index e4ca113cb1..9efb6c42df 100644 --- a/apps/loopover-ui/src/routes/docs.miner-workflow.tsx +++ b/apps/loopover-ui/src/routes/docs.miner-workflow.tsx @@ -4,18 +4,18 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/miner-workflow.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/WorkflowMirror/ // AmsObservabilityCallout primitives -- not fumadocs-ui's bundled components. See -// docs-source.ts's comment for why the loader below resolves only a plain, +// docs-source.server.ts's comment for why the loader below resolves only a plain, // serializable path string. export const Route = createFileRoute("/docs/miner-workflow")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["miner-workflow"]); + const page = await getDocPage({ data: { slugs: ["miner-workflow"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.owner-checklist.tsx b/apps/loopover-ui/src/routes/docs.owner-checklist.tsx index d6acd70873..83899c77e9 100644 --- a/apps/loopover-ui/src/routes/docs.owner-checklist.tsx +++ b/apps/loopover-ui/src/routes/docs.owner-checklist.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/owner-checklist.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock primitives -- -// not fumadocs-ui's bundled components. See docs-source.ts's comment for why the +// not fumadocs-ui's bundled components. See docs-source.server.ts's comment for why the // loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/owner-checklist")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["owner-checklist"]); + const page = await getDocPage({ data: { slugs: ["owner-checklist"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.privacy-security.tsx b/apps/loopover-ui/src/routes/docs.privacy-security.tsx index 7b71e3e8a7..8f5ae53556 100644 --- a/apps/loopover-ui/src/routes/docs.privacy-security.tsx +++ b/apps/loopover-ui/src/routes/docs.privacy-security.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/privacy-security.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock primitives -- -// not fumadocs-ui's bundled components. See docs-source.ts's comment for why the +// not fumadocs-ui's bundled components. See docs-source.server.ts's comment for why the // loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/privacy-security")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["privacy-security"]); + const page = await getDocPage({ data: { slugs: ["privacy-security"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.quickstart.tsx b/apps/loopover-ui/src/routes/docs.quickstart.tsx index cceb20f406..5bec72642a 100644 --- a/apps/loopover-ui/src/routes/docs.quickstart.tsx +++ b/apps/loopover-ui/src/routes/docs.quickstart.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/quickstart.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock primitives -- -// not fumadocs-ui's bundled components. See docs-source.ts's comment for why the +// not fumadocs-ui's bundled components. See docs-source.server.ts's comment for why the // loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/quickstart")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["quickstart"]); + const page = await getDocPage({ data: { slugs: ["quickstart"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.scoreability.tsx b/apps/loopover-ui/src/routes/docs.scoreability.tsx index b2624b1073..602703a2d6 100644 --- a/apps/loopover-ui/src/routes/docs.scoreability.tsx +++ b/apps/loopover-ui/src/routes/docs.scoreability.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/scoreability.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock primitives -- -// not fumadocs-ui's bundled components. See docs-source.ts's comment for why the +// not fumadocs-ui's bundled components. See docs-source.server.ts's comment for why the // loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/scoreability")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["scoreability"]); + const page = await getDocPage({ data: { slugs: ["scoreability"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.self-hosting-ai-providers.tsx b/apps/loopover-ui/src/routes/docs.self-hosting-ai-providers.tsx index 7735afe3bd..2fe389ae10 100644 --- a/apps/loopover-ui/src/routes/docs.self-hosting-ai-providers.tsx +++ b/apps/loopover-ui/src/routes/docs.self-hosting-ai-providers.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/self-hosting-ai-providers.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock primitives -- -// not fumadocs-ui's bundled components. See docs-source.ts's comment for why the +// not fumadocs-ui's bundled components. See docs-source.server.ts's comment for why the // loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/self-hosting-ai-providers")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["self-hosting-ai-providers"]); + const page = await getDocPage({ data: { slugs: ["self-hosting-ai-providers"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.self-hosting-backup-scaling.tsx b/apps/loopover-ui/src/routes/docs.self-hosting-backup-scaling.tsx index 0a3b218fb4..082aa018ce 100644 --- a/apps/loopover-ui/src/routes/docs.self-hosting-backup-scaling.tsx +++ b/apps/loopover-ui/src/routes/docs.self-hosting-backup-scaling.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/self-hosting-backup-scaling.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock primitives -- -// not fumadocs-ui's bundled components. See docs-source.ts's comment for why the +// not fumadocs-ui's bundled components. See docs-source.server.ts's comment for why the // loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/self-hosting-backup-scaling")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["self-hosting-backup-scaling"]); + const page = await getDocPage({ data: { slugs: ["self-hosting-backup-scaling"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.self-hosting-configuration.tsx b/apps/loopover-ui/src/routes/docs.self-hosting-configuration.tsx index 3649524310..39ef1102a3 100644 --- a/apps/loopover-ui/src/routes/docs.self-hosting-configuration.tsx +++ b/apps/loopover-ui/src/routes/docs.self-hosting-configuration.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/self-hosting-configuration.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock primitives -- -// not fumadocs-ui's bundled components. See docs-source.ts's comment for why the +// not fumadocs-ui's bundled components. See docs-source.server.ts's comment for why the // loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/self-hosting-configuration")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["self-hosting-configuration"]); + const page = await getDocPage({ data: { slugs: ["self-hosting-configuration"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.self-hosting-docs-audit.tsx b/apps/loopover-ui/src/routes/docs.self-hosting-docs-audit.tsx index 2932c6404b..2ac40c26ac 100644 --- a/apps/loopover-ui/src/routes/docs.self-hosting-docs-audit.tsx +++ b/apps/loopover-ui/src/routes/docs.self-hosting-docs-audit.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/self-hosting-docs-audit.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock primitives -- -// not fumadocs-ui's bundled components. See docs-source.ts's comment for why the +// not fumadocs-ui's bundled components. See docs-source.server.ts's comment for why the // loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/self-hosting-docs-audit")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["self-hosting-docs-audit"]); + const page = await getDocPage({ data: { slugs: ["self-hosting-docs-audit"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.self-hosting-github-app.tsx b/apps/loopover-ui/src/routes/docs.self-hosting-github-app.tsx index ad9f9ec51b..c7b91f7323 100644 --- a/apps/loopover-ui/src/routes/docs.self-hosting-github-app.tsx +++ b/apps/loopover-ui/src/routes/docs.self-hosting-github-app.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/self-hosting-github-app.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/self-hosting-github-app")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["self-hosting-github-app"]); + const page = await getDocPage({ data: { slugs: ["self-hosting-github-app"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.self-hosting-operations.tsx b/apps/loopover-ui/src/routes/docs.self-hosting-operations.tsx index 98f495967c..d67ed14a9d 100644 --- a/apps/loopover-ui/src/routes/docs.self-hosting-operations.tsx +++ b/apps/loopover-ui/src/routes/docs.self-hosting-operations.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/self-hosting-operations.mdx via fumadocs-mdx's browser // entry (docsClientLoader), through the existing DocsPage/Callout/CodeBlock -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/self-hosting-operations")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["self-hosting-operations"]); + const page = await getDocPage({ data: { slugs: ["self-hosting-operations"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.self-hosting-quickstart.tsx b/apps/loopover-ui/src/routes/docs.self-hosting-quickstart.tsx index d0af26119a..1659969e32 100644 --- a/apps/loopover-ui/src/routes/docs.self-hosting-quickstart.tsx +++ b/apps/loopover-ui/src/routes/docs.self-hosting-quickstart.tsx @@ -4,20 +4,20 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // SPIKE (#6037): rendered from content/docs/self-hosting-quickstart.mdx via fumadocs-mdx's // browser entry (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow // primitives -- not fumadocs-ui's bundled components. The `loader` below runs server-only and // resolves nothing but a plain, serializable path string via docs-source.ts's collections/server // -- never the live MDX component -- which is what avoids the client-bundle crash that a direct -// collections/server import from route-module scope hits (see docs-source.ts's comment). Kept at +// collections/server import from route-module scope hits (see docs-source.server.ts's comment). Kept at // the same route/URL as the pre-migration hand-built page to prove visual output is unchanged. export const Route = createFileRoute("/docs/self-hosting-quickstart")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["self-hosting-quickstart"]); + const page = await getDocPage({ data: { slugs: ["self-hosting-quickstart"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.self-hosting-rag.tsx b/apps/loopover-ui/src/routes/docs.self-hosting-rag.tsx index f53d55fd5c..fcb1871989 100644 --- a/apps/loopover-ui/src/routes/docs.self-hosting-rag.tsx +++ b/apps/loopover-ui/src/routes/docs.self-hosting-rag.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/self-hosting-rag.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/self-hosting-rag")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["self-hosting-rag"]); + const page = await getDocPage({ data: { slugs: ["self-hosting-rag"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.self-hosting-rees-analyzers.tsx b/apps/loopover-ui/src/routes/docs.self-hosting-rees-analyzers.tsx index 099a66aaab..2399cb6559 100644 --- a/apps/loopover-ui/src/routes/docs.self-hosting-rees-analyzers.tsx +++ b/apps/loopover-ui/src/routes/docs.self-hosting-rees-analyzers.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/self-hosting-rees-analyzers.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/self-hosting-rees-analyzers")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["self-hosting-rees-analyzers"]); + const page = await getDocPage({ data: { slugs: ["self-hosting-rees-analyzers"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.self-hosting-rees.tsx b/apps/loopover-ui/src/routes/docs.self-hosting-rees.tsx index d4c88a7bb4..9169d7e264 100644 --- a/apps/loopover-ui/src/routes/docs.self-hosting-rees.tsx +++ b/apps/loopover-ui/src/routes/docs.self-hosting-rees.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/self-hosting-rees.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/self-hosting-rees")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["self-hosting-rees"]); + const page = await getDocPage({ data: { slugs: ["self-hosting-rees"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.self-hosting-release-checklist.tsx b/apps/loopover-ui/src/routes/docs.self-hosting-release-checklist.tsx index e4d0418868..b39a55c7b6 100644 --- a/apps/loopover-ui/src/routes/docs.self-hosting-release-checklist.tsx +++ b/apps/loopover-ui/src/routes/docs.self-hosting-release-checklist.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/self-hosting-release-checklist.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/self-hosting-release-checklist")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["self-hosting-release-checklist"]); + const page = await getDocPage({ data: { slugs: ["self-hosting-release-checklist"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.self-hosting-releases.tsx b/apps/loopover-ui/src/routes/docs.self-hosting-releases.tsx index dc5fb27399..772f6e3b24 100644 --- a/apps/loopover-ui/src/routes/docs.self-hosting-releases.tsx +++ b/apps/loopover-ui/src/routes/docs.self-hosting-releases.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/self-hosting-releases.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/self-hosting-releases")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["self-hosting-releases"]); + const page = await getDocPage({ data: { slugs: ["self-hosting-releases"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.self-hosting-security.tsx b/apps/loopover-ui/src/routes/docs.self-hosting-security.tsx index 9e12d097f2..37d641105f 100644 --- a/apps/loopover-ui/src/routes/docs.self-hosting-security.tsx +++ b/apps/loopover-ui/src/routes/docs.self-hosting-security.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/self-hosting-security.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/self-hosting-security")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["self-hosting-security"]); + const page = await getDocPage({ data: { slugs: ["self-hosting-security"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.self-hosting-troubleshooting.tsx b/apps/loopover-ui/src/routes/docs.self-hosting-troubleshooting.tsx index 2b55bed78a..87da44cadf 100644 --- a/apps/loopover-ui/src/routes/docs.self-hosting-troubleshooting.tsx +++ b/apps/loopover-ui/src/routes/docs.self-hosting-troubleshooting.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/self-hosting-troubleshooting.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/self-hosting-troubleshooting")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["self-hosting-troubleshooting"]); + const page = await getDocPage({ data: { slugs: ["self-hosting-troubleshooting"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.self-hosting-unified-ams-orb.tsx b/apps/loopover-ui/src/routes/docs.self-hosting-unified-ams-orb.tsx index 06c66c462d..b9d1c4497d 100644 --- a/apps/loopover-ui/src/routes/docs.self-hosting-unified-ams-orb.tsx +++ b/apps/loopover-ui/src/routes/docs.self-hosting-unified-ams-orb.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/self-hosting-unified-ams-orb.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock/FeatureRow -// primitives -- not fumadocs-ui's bundled components. See docs-source.ts's comment +// primitives -- not fumadocs-ui's bundled components. See docs-source.server.ts's comment // for why the loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/self-hosting-unified-ams-orb")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["self-hosting-unified-ams-orb"]); + const page = await getDocPage({ data: { slugs: ["self-hosting-unified-ams-orb"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.troubleshooting.tsx b/apps/loopover-ui/src/routes/docs.troubleshooting.tsx index 372dad4752..646630ed4b 100644 --- a/apps/loopover-ui/src/routes/docs.troubleshooting.tsx +++ b/apps/loopover-ui/src/routes/docs.troubleshooting.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/troubleshooting.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock primitives -- -// not fumadocs-ui's bundled components. See docs-source.ts's comment for why the +// not fumadocs-ui's bundled components. See docs-source.server.ts's comment for why the // loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/troubleshooting")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["troubleshooting"]); + const page = await getDocPage({ data: { slugs: ["troubleshooting"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.tuning.tsx b/apps/loopover-ui/src/routes/docs.tuning.tsx index 806fb0c206..50c536b5bc 100644 --- a/apps/loopover-ui/src/routes/docs.tuning.tsx +++ b/apps/loopover-ui/src/routes/docs.tuning.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/tuning.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock primitives -- -// not fumadocs-ui's bundled components. See docs-source.ts's comment for why the +// not fumadocs-ui's bundled components. See docs-source.server.ts's comment for why the // loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/tuning")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["tuning"]); + const page = await getDocPage({ data: { slugs: ["tuning"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [ diff --git a/apps/loopover-ui/src/routes/docs.upstream-drift.tsx b/apps/loopover-ui/src/routes/docs.upstream-drift.tsx index 87d671e77e..ad726005d5 100644 --- a/apps/loopover-ui/src/routes/docs.upstream-drift.tsx +++ b/apps/loopover-ui/src/routes/docs.upstream-drift.tsx @@ -4,17 +4,17 @@ import { Suspense } from "react"; import { DocsPage } from "@/components/site/docs-page"; import { LoadingState } from "@/components/site/state-views"; import { docsClientLoader } from "@/lib/docs-client-loader"; +import { getDocPage } from "@/lib/docs-source.functions"; // Rendered from content/docs/upstream-drift.mdx via fumadocs-mdx's browser entry // (docsClientLoader), through the existing DocsPage/Callout/CodeBlock primitives -- -// not fumadocs-ui's bundled components. See docs-source.ts's comment for why the +// not fumadocs-ui's bundled components. See docs-source.server.ts's comment for why the // loader below resolves only a plain, serializable path string. export const Route = createFileRoute("/docs/upstream-drift")({ loader: async () => { - const { docsSource } = await import("@/lib/docs-source"); - const page = docsSource.getPage(["upstream-drift"]); + const page = await getDocPage({ data: { slugs: ["upstream-drift"] } }); if (!page) throw notFound(); - return { path: page.path, title: page.data.title, description: page.data.description }; + return page; }, head: () => ({ meta: [