Vite
Tanstack Start
Use Fumadocs MDX with Tanstack Start & Router
Setup
npm i fumadocs-mdx fumadocs-core @types/mdx
Create the configuration file:
import { defineConfig, defineDocs } from 'fumadocs-mdx/config';
export const docs = defineDocs({
dir: 'content/docs',
});
export default defineConfig();
Add the Vite plugin:
import react from '@vitejs/plugin-react';
import { tanstackStart } from '@tanstack/react-start/plugin/vite';
import { defineConfig } from 'vite';
import tsConfigPaths from 'vite-tsconfig-paths';
import tailwindcss from '@tailwindcss/vite';
import mdx from 'fumadocs-mdx/vite';
export default defineConfig({
server: {
port: 3000,
},
plugins: [
mdx(await import('./source.config')),
tailwindcss(),
tsConfigPaths({
projects: ['./tsconfig.json'],
}),
tanstackStart({
customViteReactPlugin: true,
prerender: {
enabled: true,
},
}),
react(),
],
});
Integrate with Fumadocs
To integrate with Fumadocs, create a lib/source.ts
file:
import { loader } from 'fumadocs-core/source';
import { create, docs } from '../../source.generated';
export const source = loader({
source: await create.sourceAsync(docs.doc, docs.meta),
baseUrl: '/docs',
});
The source.generated.ts
file will be generated when you run development server or production build.
Done
The configuration is now finished.
Examples
Rendering Content
As Tanstack Start doesn't support RSC at the moment, use createClientLoader()
to lazy load MDX content as a component on browser.
For example:
import { createFileRoute, notFound } from '@tanstack/react-router';
import { createServerFn } from '@tanstack/react-start';
import { source } from '@/lib/source';
import { docs } from '../../../source.generated';
import { createClientLoader } from 'fumadocs-mdx/runtime/vite';
export const Route = createFileRoute('/docs/$')({
component: Page,
loader: async ({ params }) => {
const data = await loader({ data: params._splat?.split('/') ?? [] });
await clientLoader.preload(data.path);
return data;
},
});
const loader = createServerFn({
method: 'GET',
})
.validator((slugs: string[]) => slugs)
.handler(async ({ data: slugs }) => {
const page = source.getPage(slugs);
if (!page) throw notFound();
return {
path: page.path,
};
});
const clientLoader = createClientLoader(docs.doc, {
id: 'docs',
component({ frontmatter, default: MDX }) {
return (
<div className="prose">
<h1>{frontmatter.title}</h1>
<MDX />
</div>
);
},
});
function Page() {
const data = Route.useLoaderData();
const Content = clientLoader.getComponent(data.path);
return <Content />;
}
As you see, the source.generated.ts
file can be imported directly:
import { docs } from './source.generated';
console.log(docs);
How is this guide?
Last updated on