Use the source primitive
Use the source primitive
createDocsSource() is the framework-neutral way to render leadtype-authored MDX in your own docs app. This page shows the wiring on top of the most common hosts.
If you're using Fumadocs specifically, use leadtype/fumadocs — it's a thinner wrapper around this same primitive.
TL;DR
The primitive itself is identical across frameworks:
Wire createMdxSourcePlugins() into your bundler's remark stack, then call source.loadPage(slug) from your framework's page renderer. The "Wire into your framework" section below has minimal setups for each host.
Install
Plus an MDX integration for your bundler (@next/mdx, @astrojs/mdx, @mdx-js/rollup, etc.).
Wire into your framework
createMdxSourcePlugins() expands <include> partials and resolves <ExtractedTypeTable> at build time, while leaving every custom tag (<Callout>, <Tabs>, <Steps>, …) as JSX for your runtime components. Set typeTableBasePath to the source root that contains referenced TypeScript files; use path.resolve(process.cwd(), "docs") only when those files intentionally live under your docs folder.
Next App Router
Astro Content Collections
Use Astro's native content collection schema for typed frontmatter. Call source.loadPage() from leadtype only when you need programmatic include resolution, search, or navigation. See Astro's content collections docs for the routing pattern.
TanStack Start
Generate docs-pages.json at build time by calling createDocsSource().listPages() from a build script and writing each page's slug, urlPath, and globKey (path relative to the catch-all route, POSIX separators).
Vite + @mdx-js/rollup (works for Vue, Solid, Svelte starters)
Nuxt
SvelteKit + mdsvex
Pattern for any other host
If your framework's MDX integration accepts a remark plugin list, leadtype works. Three pieces every time:
- Add
createMdxSourcePlugins()to the remark list so<include>and<ExtractedTypeTable>resolve at build time. - Implement components against the tag types from
leadtype/mdx. - Call
createDocsSource()if you want navigation, search, or programmatic page loading.
Implement the tag components
Import prop types from leadtype/mdx and implement against your framework:
The full tag inventory and intersection patterns for React, Vue, Svelte, Solid, and Astro live in leadtype/mdx.
Build the sidebar from navigation
Each page carries a toc field (DocsTableOfContentsItem[]) you can render as an "On this page" rail.
Match heading slugs
source.loadPage().toc uses slugifyDocsHeading to derive anchor IDs. Your rendered heading components need matching id attributes:
Wire Heading2 (and h3, etc.) into your mdxComponents map. Authors can still pin an explicit id on a heading.
Build a search index
For provider-specific search (Vercel AI, TanStack, Cloudflare), feed the bundle into a leadtype/search/* adapter — see Add search.
Troubleshooting
<include>tags survive into the rendered output. You forgot to addcreateMdxSourcePlugins()to your MDX compiler's remark plugin list.<ExtractedTypeTable>renders unresolved. The source preset converts these to<TypeTable>only whenextractTypeFromFilesucceeds. Make suretypescriptis installed in the docs app andtypeTableBasePathresolves to the project that contains the type.- TOC links don't scroll. Rendered heading IDs don't match. Wire
slugifyDocsHeadinginto your heading components. - Sidebar order doesn't match
llms.txt. Your app and the CLI are loading differentdocs.config.tsfiles. Centralize the config and import it in both.
Reference
leadtype/mdx— tag types,createMdxSourcePlugins(), include helperscreateDocsSource— full API surface for the primitiveleadtype/fumadocs— fumadocs adapter recipe