New standalone app at docs-site/ — Fumadocs (fumadocs-core/ui 16, fumadocs-mdx
15) on TanStack Start (Vite 7 + nitro-v2 bun preset, React 19, Tailwind 4),
mirroring the web/ console stack but with no auth/i18n/orval — docs stay public.
- catch-all docs route (routes/docs/$.tsx), Orama search (routes/api/search.ts),
RootProvider shell, MDX component map, shared nav, custom 404
- content/docs/: hand-written index.mdx + meta.json nav, plus 7 pages imported
from repo docs/ + README (leading H1 stripped, YAML frontmatter added; kept as
.md so existing </{ don't trip MDX JSX). Content is a one-time snapshot.
- mdx() is plugins[0]; tsconfig collections/* -> ./.source/*; SSR search variant;
@source for fumadocs-ui classes. Generated .source/routeTree/dist/.output ignored.
Verified: bun run build (client+SSR+nitro) green, tsc clean, dev + prod servers
serve all routes 200 with SSR content + nav, search returns hits, 404 works.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import { createFileRoute, notFound } from '@tanstack/react-router'
|
||||
import { DocsLayout } from 'fumadocs-ui/layouts/docs'
|
||||
import { createServerFn } from '@tanstack/react-start'
|
||||
import { source } from '@/lib/source'
|
||||
import browserCollections from 'collections/browser'
|
||||
import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/layouts/docs/page'
|
||||
import { baseOptions } from '@/lib/layout.shared'
|
||||
import { useFumadocsLoader } from 'fumadocs-core/source/client'
|
||||
import { Suspense } from 'react'
|
||||
import { useMDXComponents } from '@/components/mdx'
|
||||
|
||||
export const Route = createFileRoute('/docs/$')({
|
||||
component: Page,
|
||||
loader: async ({ params }) => {
|
||||
const slugs = params._splat?.split('/') ?? []
|
||||
const data = await serverLoader({ data: slugs })
|
||||
await clientLoader.preload(data.path)
|
||||
return data
|
||||
},
|
||||
})
|
||||
|
||||
const serverLoader = createServerFn({
|
||||
method: 'GET',
|
||||
})
|
||||
.validator((slugs: string[]) => slugs)
|
||||
.handler(async ({ data: slugs }) => {
|
||||
const page = source.getPage(slugs)
|
||||
if (!page) throw notFound()
|
||||
|
||||
return {
|
||||
path: page.path,
|
||||
pageTree: await source.serializePageTree(source.getPageTree()),
|
||||
}
|
||||
})
|
||||
|
||||
const clientLoader = browserCollections.docs.createClientLoader({
|
||||
component({ toc, frontmatter, default: MDX }, _props: undefined) {
|
||||
return (
|
||||
<DocsPage toc={toc}>
|
||||
<DocsTitle>{frontmatter.title}</DocsTitle>
|
||||
<DocsDescription>{frontmatter.description}</DocsDescription>
|
||||
<DocsBody>
|
||||
<MDX components={useMDXComponents()} />
|
||||
</DocsBody>
|
||||
</DocsPage>
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
function Page() {
|
||||
const data = useFumadocsLoader(Route.useLoaderData())
|
||||
|
||||
return (
|
||||
<DocsLayout {...baseOptions()} tree={data.pageTree}>
|
||||
<Suspense>{clientLoader.useContent(data.path)}</Suspense>
|
||||
</DocsLayout>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user