From 6c6dfa2b5e1a79742a0ed7a5811a42b9f26ebacf Mon Sep 17 00:00:00 2001
From: Kaylee <65376239+KayleeWilliams@users.noreply.github.com>
Date: Wed, 13 May 2026 00:19:12 -0700
Subject: [PATCH 1/5] Add v1 headless integration surface and polish docs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
New public API:
- `createDocsSource()` at the root — framework-neutral source primitive
(navigation, page loading, search, includes) for Next, Astro, Vite,
Nuxt, SvelteKit, and any MDX-aware bundler
- `leadtype/mdx` subpath — tag prop contracts for every custom MDX tag
plus `mdxSourcePlugins` (build-time include + ExtractedTypeTable
resolution, leaves custom tags as JSX)
- `leadtype/fumadocs` subpath — thin Source adapter for fumadocs-core,
walks pages + meta.json. Optional peer dep on fumadocs-core >= 15
New helpers:
- `convertMdxFile(path, plugins)` — in-memory MDX → {ast, frontmatter,
data, markdown}
- `resolveInclude` / `parseIncludeSpecifier` / `extractMdxSection` /
`resolveIncludePath` — standalone include resolution, no remark
transform required
- `remarkResolveTypeTableJsx` — JSX-preserving variant of the type-table
plugin for the source preset
Frontmatter:
- New optional `order:` field for sidebar ordering within a group
Navigation:
- `resolveDocsNavigation` accepts an optional `docsDirName` config
(defaults to "docs") for projects whose docs folder isn't named docs/
Bug fixes:
- Mermaid ` ` syntax preserved in agent-flattened markdown (was
being mangled to "/" and "-" by two separate passes, breaking
downstream renderers)
- Mermaid plugin's backtick stripper handles inline template-literal
form, not just backticks-on-their-own-lines
Docs polish:
- New `/docs/build/build-a-docs-site` umbrella with explicit decision
tree (source primitive vs CLI artifacts)
- New `/docs/build/use-the-source-primitive` — multi-framework
walkthrough with anchor-linkable per-host sections
- New `/docs/build/integrate-with-fumadocs` — first-party fumadocs
recipe with TL;DR
- New `/docs/build/generate-static-artifacts` — CLI workflow
- New reference pages `/docs/reference/mdx` and `/docs/reference/source`
- Quickstart rewritten as framework-neutral primitive walkthrough
(was Next-flavored CLI walkthrough); home page tightened; deleted
the overlapping connect-docs-site + render-mdx-and-toc pages
- Code blocks now use `title="..."` fence meta instead of leading
`// filename` comments — cleaner rendering via rehype-code
- apps/example refactored to a single `[[...slug]]` catch-all powered
by a createDocsSource-generated manifest (was 18 hand-rolled route
files)
- New apps/fumadocs-example demonstrates leadtype/fumadocs end-to-end
with c15t docs as content
---
.../v1-public-surface-and-docs-polish.md | 30 +
apps/example/package.json | 3 +-
apps/example/scripts/docs-source-manifest.ts | 56 ++
.../src/components/docs-mdx/callout.tsx | 33 +-
.../src/generated/agent-readability.json | 791 +++++++++++++++---
apps/example/src/generated/docs-nav.json | 765 ++++++++++++++---
apps/example/src/generated/docs-pages.json | 341 ++++++++
.../src/generated/docs-search-content.json | 2 +-
.../src/generated/docs-search-index.json | 2 +-
apps/example/src/routeTree.gen.ts | 395 +--------
apps/example/src/routes/docs/$.tsx | 87 ++
.../src/routes/docs/authoring/components.tsx | 14 -
.../src/routes/docs/authoring/frontmatter.tsx | 14 -
.../src/routes/docs/build/add-search.tsx | 14 -
.../routes/docs/build/connect-docs-site.tsx | 14 -
.../docs/build/optimize-docs-for-agents.tsx | 14 -
.../routes/docs/build/render-mdx-and-toc.tsx | 14 -
.../src/routes/docs/build/validate-in-ci.tsx | 14 -
apps/example/src/routes/docs/how-it-works.tsx | 14 -
apps/example/src/routes/docs/methodology.tsx | 14 -
.../src/routes/docs/package-docs/bundle.tsx | 14 -
apps/example/src/routes/docs/quickstart.tsx | 14 -
.../example/src/routes/docs/reference/cli.tsx | 14 -
.../src/routes/docs/reference/convert.tsx | 14 -
.../src/routes/docs/reference/evals.tsx | 14 -
.../src/routes/docs/reference/lint.tsx | 14 -
.../example/src/routes/docs/reference/llm.tsx | 14 -
.../src/routes/docs/reference/remark.tsx | 14 -
.../src/routes/docs/reference/search.tsx | 14 -
apps/example/vite.config.ts | 12 +-
.../app/docs/[[...slug]]/page.tsx | 70 ++
apps/fumadocs-example/app/docs/layout.tsx | 57 ++
apps/fumadocs-example/app/global.css | 9 +
apps/fumadocs-example/app/layout.tsx | 19 +
apps/fumadocs-example/app/page.tsx | 21 +
apps/fumadocs-example/css.d.ts | 1 +
.../lib/framework-switcher.tsx | 75 ++
apps/fumadocs-example/lib/mdx-components.tsx | 243 ++++++
apps/fumadocs-example/lib/source.ts | 29 +
apps/fumadocs-example/mdx-components.tsx | 13 +
apps/fumadocs-example/next-env.d.ts | 6 +
apps/fumadocs-example/next.config.mjs | 27 +
apps/fumadocs-example/package.json | 37 +
apps/fumadocs-example/postcss.config.mjs | 5 +
apps/fumadocs-example/scripts/setup-source.ts | 36 +
apps/fumadocs-example/tsconfig.json | 29 +
bun.lock | 347 +++++++-
docs/authoring/components.mdx | 2 +-
docs/authoring/frontmatter.mdx | 6 +-
docs/build/add-search.mdx | 1 +
docs/build/build-a-docs-site.mdx | 83 ++
...site.mdx => generate-static-artifacts.mdx} | 90 +-
docs/build/integrate-with-fumadocs.mdx | 148 ++++
docs/build/optimize-docs-for-agents.mdx | 3 +-
docs/build/render-mdx-and-toc.mdx | 94 ---
docs/build/use-the-source-primitive.mdx | 238 ++++++
docs/build/validate-in-ci.mdx | 1 +
docs/docs.config.ts | 3 +-
docs/index.mdx | 40 +-
docs/methodology.mdx | 16 +-
docs/package-docs/bundle.mdx | 7 +-
docs/quickstart.mdx | 117 +--
docs/reference/evals.mdx | 2 +-
docs/reference/llm.mdx | 2 +-
docs/reference/mdx.mdx | 257 ++++++
docs/reference/source.mdx | 197 +++++
packages/leadtype/package.json | 13 +
packages/leadtype/rollup.config.ts | 2 +
packages/leadtype/src/cli.test.ts | 12 +-
packages/leadtype/src/convert/convert.test.ts | 50 +-
packages/leadtype/src/convert/convert.ts | 91 +-
packages/leadtype/src/convert/index.ts | 2 +
packages/leadtype/src/fumadocs/index.ts | 153 ++++
packages/leadtype/src/index.ts | 22 +-
.../src/internal/package-surface.test.ts | 2 +
packages/leadtype/src/lint/schema.ts | 8 +
packages/leadtype/src/llm/llm.ts | 51 +-
packages/leadtype/src/mdx/index.ts | 78 ++
packages/leadtype/src/mdx/source-preset.ts | 35 +
packages/leadtype/src/mdx/tag-types.ts | 316 +++++++
.../src/remark/plugins/include.remark.test.ts | 176 ++++
.../src/remark/plugins/include.remark.ts | 250 ++++--
.../src/remark/plugins/mermaid.remark.ts | 23 +-
.../remark/plugins/type-table-jsx.remark.ts | 164 ++++
packages/leadtype/src/source/index.ts | 364 ++++++++
packages/leadtype/src/source/source.test.ts | 177 ++++
86 files changed, 5828 insertions(+), 1261 deletions(-)
create mode 100644 .changeset/v1-public-surface-and-docs-polish.md
create mode 100644 apps/example/scripts/docs-source-manifest.ts
create mode 100644 apps/example/src/generated/docs-pages.json
create mode 100644 apps/example/src/routes/docs/$.tsx
delete mode 100644 apps/example/src/routes/docs/authoring/components.tsx
delete mode 100644 apps/example/src/routes/docs/authoring/frontmatter.tsx
delete mode 100644 apps/example/src/routes/docs/build/add-search.tsx
delete mode 100644 apps/example/src/routes/docs/build/connect-docs-site.tsx
delete mode 100644 apps/example/src/routes/docs/build/optimize-docs-for-agents.tsx
delete mode 100644 apps/example/src/routes/docs/build/render-mdx-and-toc.tsx
delete mode 100644 apps/example/src/routes/docs/build/validate-in-ci.tsx
delete mode 100644 apps/example/src/routes/docs/how-it-works.tsx
delete mode 100644 apps/example/src/routes/docs/methodology.tsx
delete mode 100644 apps/example/src/routes/docs/package-docs/bundle.tsx
delete mode 100644 apps/example/src/routes/docs/quickstart.tsx
delete mode 100644 apps/example/src/routes/docs/reference/cli.tsx
delete mode 100644 apps/example/src/routes/docs/reference/convert.tsx
delete mode 100644 apps/example/src/routes/docs/reference/evals.tsx
delete mode 100644 apps/example/src/routes/docs/reference/lint.tsx
delete mode 100644 apps/example/src/routes/docs/reference/llm.tsx
delete mode 100644 apps/example/src/routes/docs/reference/remark.tsx
delete mode 100644 apps/example/src/routes/docs/reference/search.tsx
create mode 100644 apps/fumadocs-example/app/docs/[[...slug]]/page.tsx
create mode 100644 apps/fumadocs-example/app/docs/layout.tsx
create mode 100644 apps/fumadocs-example/app/global.css
create mode 100644 apps/fumadocs-example/app/layout.tsx
create mode 100644 apps/fumadocs-example/app/page.tsx
create mode 100644 apps/fumadocs-example/css.d.ts
create mode 100644 apps/fumadocs-example/lib/framework-switcher.tsx
create mode 100644 apps/fumadocs-example/lib/mdx-components.tsx
create mode 100644 apps/fumadocs-example/lib/source.ts
create mode 100644 apps/fumadocs-example/mdx-components.tsx
create mode 100644 apps/fumadocs-example/next-env.d.ts
create mode 100644 apps/fumadocs-example/next.config.mjs
create mode 100644 apps/fumadocs-example/package.json
create mode 100644 apps/fumadocs-example/postcss.config.mjs
create mode 100644 apps/fumadocs-example/scripts/setup-source.ts
create mode 100644 apps/fumadocs-example/tsconfig.json
create mode 100644 docs/build/build-a-docs-site.mdx
rename docs/build/{connect-docs-site.mdx => generate-static-artifacts.mdx} (58%)
create mode 100644 docs/build/integrate-with-fumadocs.mdx
delete mode 100644 docs/build/render-mdx-and-toc.mdx
create mode 100644 docs/build/use-the-source-primitive.mdx
create mode 100644 docs/reference/mdx.mdx
create mode 100644 docs/reference/source.mdx
create mode 100644 packages/leadtype/src/fumadocs/index.ts
create mode 100644 packages/leadtype/src/mdx/index.ts
create mode 100644 packages/leadtype/src/mdx/source-preset.ts
create mode 100644 packages/leadtype/src/mdx/tag-types.ts
create mode 100644 packages/leadtype/src/remark/plugins/include.remark.test.ts
create mode 100644 packages/leadtype/src/remark/plugins/type-table-jsx.remark.ts
create mode 100644 packages/leadtype/src/source/index.ts
create mode 100644 packages/leadtype/src/source/source.test.ts
diff --git a/.changeset/v1-public-surface-and-docs-polish.md b/.changeset/v1-public-surface-and-docs-polish.md
new file mode 100644
index 0000000..5534577
--- /dev/null
+++ b/.changeset/v1-public-surface-and-docs-polish.md
@@ -0,0 +1,30 @@
+---
+"leadtype": minor
+---
+
+Ship the v1 headless integration surface plus docs polish.
+
+**New public API**
+
+- `createDocsSource({ contentDir })` at the root — framework-neutral docs source primitive returning navigation, page loading, search index, and standalone include resolution. Works with Next App Router, Astro, Vite + Vue/Solid/Svelte, Nuxt, SvelteKit, and any MDX-aware bundler.
+- `leadtype/mdx` subpath — typed prop contracts for every custom MDX tag (`CalloutProps`, `TabsProps`, `StepProps`, `TypeTableProps`, …) plus `mdxSourcePlugins` (a remark preset that expands `` and resolves `` at build time while leaving custom tags as JSX). Framework-neutral — `children` is typed as `unknown` so consumers intersect with React/Vue/Svelte/Solid/Astro child types.
+- `leadtype/fumadocs` subpath — thin adapter mapping `createDocsSource()` to fumadocs-core's `Source` interface, including `meta.json` walking. `fumadocs-core >= 15` is an optional peer dependency.
+
+**New helpers**
+
+- `convertMdxFile(path, plugins)` from `leadtype/convert` — returns `{ ast, frontmatter, data, markdown }` in memory for a single MDX file.
+- `resolveInclude(specifier, options)` from `leadtype/mdx` — standalone include resolver, no remark transform required. Plus `parseIncludeSpecifier`, `extractMdxSection`, `resolveIncludePath`.
+- `remarkResolveTypeTableJsx` — source-preset variant of the type-table plugin that emits `` JSX (vs. the existing markdown-flattening variant).
+
+**Frontmatter contract**
+
+- New optional `order:` field. Pages with explicit order sort first within their group (ascending); pages without `order` fall back to alphabetical urlPath ordering. Conventionally numbered in tens for insertion room.
+
+**Navigation**
+
+- `resolveDocsNavigation` accepts an optional `docsDirName` config field (defaults to `"docs"`) for projects whose docs folder isn't named `docs/`.
+
+**Bug fixes**
+
+- Mermaid blocks in agent-flattened markdown no longer destroy ` ` line-break syntax (was being replaced with ` / ` and ` - ` in two passes). Mermaid renderers now receive valid syntax with multi-line node labels intact.
+- The mermaid plugin's outer-backtick stripper now handles the common `` chart={`flowchart LR\n...`} `` inline form, not just backticks-on-their-own-lines.
diff --git a/apps/example/package.json b/apps/example/package.json
index 460e1aa..21bc34f 100644
--- a/apps/example/package.json
+++ b/apps/example/package.json
@@ -17,7 +17,8 @@
"pipeline:convert": "bun run scripts/mdx-convert.ts",
"pipeline:llm": "bun run scripts/llm-generate.ts",
"pipeline:search": "bun run scripts/search-generate.ts",
- "pipeline:build": "bun run pipeline:convert && bun run pipeline:llm && bun run pipeline:search",
+ "pipeline:source-manifest": "bun run scripts/docs-source-manifest.ts",
+ "pipeline:build": "bun run pipeline:convert && bun run pipeline:llm && bun run pipeline:search && bun run pipeline:source-manifest",
"pipeline:test": "bun run scripts/test-pipeline.ts",
"pipeline:setup-real": "bun run scripts/setup-real-content.ts",
"pipeline:test-real": "bun run pipeline:setup-real && bun run scripts/test-real.ts",
diff --git a/apps/example/scripts/docs-source-manifest.ts b/apps/example/scripts/docs-source-manifest.ts
new file mode 100644
index 0000000..eab1002
--- /dev/null
+++ b/apps/example/scripts/docs-source-manifest.ts
@@ -0,0 +1,56 @@
+#!/usr/bin/env bun
+/**
+ * Build-time dogfood of `createDocsSource()` — the v1 source primitive.
+ *
+ * Writes `src/generated/docs-pages.json` with `{ slug, urlPath, title,
+ * description, relativePath, extension }` for every page in `/docs`. The
+ * catch-all docs route uses this manifest to wire slugs → MDX modules
+ * without hand-rolling one route file per page.
+ *
+ * The companion `llm-generate.ts` script still emits the on-disk
+ * `llms.txt` / `agent-readability.json` artifacts via the older composed
+ * APIs. The two paths coexist deliberately — they demonstrate both
+ * integration shapes from `/docs/build/build-a-docs-site`.
+ */
+
+import { mkdir, writeFile } from "node:fs/promises";
+import { dirname, join, relative } from "node:path";
+import { fileURLToPath } from "node:url";
+import { createDocsSource } from "leadtype";
+import docsConfig from "../../../docs/docs.config";
+
+const scriptsRoot = dirname(fileURLToPath(import.meta.url));
+const appRoot = join(scriptsRoot, "..");
+const repoRoot = join(appRoot, "..", "..");
+const contentDir = join(repoRoot, "docs");
+const generatedDir = join(appRoot, "src", "generated");
+const manifestPath = join(generatedDir, "docs-pages.json");
+
+const source = await createDocsSource({
+ contentDir,
+ baseUrl: process.env.BASE_URL?.trim() || "https://leadtype.dev",
+ groups: docsConfig.groups,
+});
+
+const pages = await source.listPages();
+
+const manifest = pages.map((page) => ({
+ slug: page.slug,
+ urlPath: page.urlPath,
+ title: page.title,
+ description: page.description,
+ relativePath: page.relativePath,
+ extension: page.extension,
+ groups: page.groups,
+ // Path the runtime catch-all can use to look up the MDX module against
+ // `import.meta.glob('../../../../docs/**/*.mdx')`. Always relative to
+ // src/routes/docs/$.tsx so the glob key matches exactly.
+ globKey: `${relative(join(appRoot, "src", "routes", "docs"), join(contentDir, page.relativePath))}${page.extension}`,
+}));
+
+await mkdir(generatedDir, { recursive: true });
+await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
+
+process.stdout.write(
+ `Wrote ${manifest.length} pages to ${relative(repoRoot, manifestPath)}\n`
+);
diff --git a/apps/example/src/components/docs-mdx/callout.tsx b/apps/example/src/components/docs-mdx/callout.tsx
index 4bc4566..226a2f0 100644
--- a/apps/example/src/components/docs-mdx/callout.tsx
+++ b/apps/example/src/components/docs-mdx/callout.tsx
@@ -1,29 +1,16 @@
+import type {
+ CalloutTypeAlias,
+ CalloutVariant,
+ CalloutProps as LeadtypeCalloutProps,
+} from "leadtype/mdx";
import type { HTMLAttributes, ReactNode } from "react";
-export type CalloutVariant =
- | "info"
- | "note"
- | "tip"
- | "warning"
- | "success"
- | "error"
- | "canary"
- | "deprecated"
- | "experimental";
+export type { CalloutTypeAlias, CalloutVariant } from "leadtype/mdx";
-/**
- * Aliases accepted by the deprecated `type` prop. Mirrors `CalloutVariant`
- * but also accepts `"warn"` (Fumadocs-style) which maps to `"warning"`.
- */
-export type CalloutTypeAlias = CalloutVariant | "warn";
-
-export type CalloutProps = HTMLAttributes & {
- variant?: CalloutVariant;
- /** @deprecated Use `variant` instead. Kept for Fumadocs-authored MDX compatibility. */
- type?: CalloutTypeAlias;
- title?: string;
- children?: ReactNode;
-};
+export type CalloutProps = Omit &
+ HTMLAttributes & {
+ children?: ReactNode;
+ };
function normalizeVariant(
variant: CalloutVariant | undefined,
diff --git a/apps/example/src/generated/agent-readability.json b/apps/example/src/generated/agent-readability.json
index 2652084..e28ec96 100644
--- a/apps/example/src/generated/agent-readability.json
+++ b/apps/example/src/generated/agent-readability.json
@@ -1,6 +1,6 @@
{
"version": 1,
- "generatedAt": "2026-05-11T23:20:44.255Z",
+ "generatedAt": "2026-05-13T06:50:55.183Z",
"baseUrl": "https://leadtype.dev",
"product": {
"name": "Leadtype",
@@ -31,7 +31,7 @@
"groups": [
"authoring"
],
- "lastModified": "2026-05-11T17:53:02.000Z"
+ "lastModified": "2026-05-12T02:59:25.000Z"
},
{
"title": "Frontmatter",
@@ -60,17 +60,43 @@
"lastModified": "2026-05-11T17:53:02.000Z"
},
{
- "title": "Connect a docs site",
- "description": "Build a shared docs app from source docs that live with the code they document.",
- "urlPath": "/docs/build/connect-docs-site",
- "absoluteUrl": "https://leadtype.dev/docs/build/connect-docs-site",
- "markdownUrlPath": "/docs/build/connect-docs-site.md",
- "markdownAbsoluteUrl": "https://leadtype.dev/docs/build/connect-docs-site.md",
- "relativePath": "build/connect-docs-site",
+ "title": "Build a docs site",
+ "description": "Pick the right leadtype integration shape for your docs app, and what each path gives you.",
+ "urlPath": "/docs/build/build-a-docs-site",
+ "absoluteUrl": "https://leadtype.dev/docs/build/build-a-docs-site",
+ "markdownUrlPath": "/docs/build/build-a-docs-site.md",
+ "markdownAbsoluteUrl": "https://leadtype.dev/docs/build/build-a-docs-site.md",
+ "relativePath": "build/build-a-docs-site",
"groups": [
"docs-site"
],
- "lastModified": "2026-05-11T17:53:02.000Z"
+ "lastModified": "2026-05-13T06:50:55.052Z"
+ },
+ {
+ "title": "Generate static artifacts",
+ "description": "Run leadtype generate from your build pipeline to write llms.txt, markdown mirrors, search index, sitemap, and agent-readability files to disk.",
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "absoluteUrl": "https://leadtype.dev/docs/build/generate-static-artifacts",
+ "markdownUrlPath": "/docs/build/generate-static-artifacts.md",
+ "markdownAbsoluteUrl": "https://leadtype.dev/docs/build/generate-static-artifacts.md",
+ "relativePath": "build/generate-static-artifacts",
+ "groups": [
+ "docs-site"
+ ],
+ "lastModified": "2026-05-13T06:50:55.038Z"
+ },
+ {
+ "title": "Integrate with Fumadocs",
+ "description": "Wire leadtype's content layer into a fumadocs app for nav, search, and includes.",
+ "urlPath": "/docs/build/integrate-with-fumadocs",
+ "absoluteUrl": "https://leadtype.dev/docs/build/integrate-with-fumadocs",
+ "markdownUrlPath": "/docs/build/integrate-with-fumadocs.md",
+ "markdownAbsoluteUrl": "https://leadtype.dev/docs/build/integrate-with-fumadocs.md",
+ "relativePath": "build/integrate-with-fumadocs",
+ "groups": [
+ "docs-site"
+ ],
+ "lastModified": "2026-05-13T06:50:55.049Z"
},
{
"title": "Optimize docs for agents",
@@ -86,17 +112,17 @@
"lastModified": "2026-05-11T17:53:02.000Z"
},
{
- "title": "Render MDX and TOC",
- "description": "Set up runtime MDX components, stable heading IDs, and a table of contents from the generated navigation manifest.",
- "urlPath": "/docs/build/render-mdx-and-toc",
- "absoluteUrl": "https://leadtype.dev/docs/build/render-mdx-and-toc",
- "markdownUrlPath": "/docs/build/render-mdx-and-toc.md",
- "markdownAbsoluteUrl": "https://leadtype.dev/docs/build/render-mdx-and-toc.md",
- "relativePath": "build/render-mdx-and-toc",
+ "title": "Use the source primitive",
+ "description": "Wire createDocsSource into Next, Astro, Vite, Nuxt, SvelteKit, or any MDX-aware bundler. Same primitive, multiple host shapes.",
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "absoluteUrl": "https://leadtype.dev/docs/build/use-the-source-primitive",
+ "markdownUrlPath": "/docs/build/use-the-source-primitive.md",
+ "markdownAbsoluteUrl": "https://leadtype.dev/docs/build/use-the-source-primitive.md",
+ "relativePath": "build/use-the-source-primitive",
"groups": [
"docs-site"
],
- "lastModified": "2026-05-11T17:53:02.000Z"
+ "lastModified": "2026-05-13T06:50:55.035Z"
},
{
"title": "Validate in CI",
@@ -152,7 +178,7 @@
},
{
"title": "Quickstart",
- "description": "Install leadtype, run the hosted-docs pipeline once, and inspect the generated artifacts.",
+ "description": "Install leadtype, author your first MDX page, and create a source. Then plug it into whatever framework you're using.",
"urlPath": "/docs/quickstart",
"absoluteUrl": "https://leadtype.dev/docs/quickstart",
"markdownUrlPath": "/docs/quickstart.md",
@@ -174,7 +200,7 @@
"groups": [
"reference"
],
- "lastModified": "2026-05-11T17:53:02.000Z"
+ "lastModified": "2026-05-12T02:59:25.000Z"
},
{
"title": "Convert",
@@ -187,7 +213,7 @@
"groups": [
"reference"
],
- "lastModified": "2026-05-09T22:38:26.000Z"
+ "lastModified": "2026-05-12T02:59:25.000Z"
},
{
"title": "Evals",
@@ -226,7 +252,20 @@
"groups": [
"reference"
],
- "lastModified": "2026-05-11T17:53:02.000Z"
+ "lastModified": "2026-05-12T02:59:25.000Z"
+ },
+ {
+ "title": "leadtype/mdx",
+ "description": "Tag type contracts and the build-time source preset for consumers rendering MDX themselves.",
+ "urlPath": "/docs/reference/mdx",
+ "absoluteUrl": "https://leadtype.dev/docs/reference/mdx",
+ "markdownUrlPath": "/docs/reference/mdx.md",
+ "markdownAbsoluteUrl": "https://leadtype.dev/docs/reference/mdx.md",
+ "relativePath": "reference/mdx",
+ "groups": [
+ "reference"
+ ],
+ "lastModified": "2026-05-13T06:50:54.985Z"
},
{
"title": "Remark plugins",
@@ -239,7 +278,7 @@
"groups": [
"reference"
],
- "lastModified": "2026-05-11T01:01:43.000Z"
+ "lastModified": "2026-05-12T02:59:25.000Z"
},
{
"title": "Search",
@@ -252,7 +291,20 @@
"groups": [
"reference"
],
- "lastModified": "2026-05-10T20:56:41.000Z"
+ "lastModified": "2026-05-12T02:59:25.000Z"
+ },
+ {
+ "title": "createDocsSource",
+ "description": "Framework-neutral docs source primitive — navigation, page loader, search index, and include resolver.",
+ "urlPath": "/docs/reference/source",
+ "absoluteUrl": "https://leadtype.dev/docs/reference/source",
+ "markdownUrlPath": "/docs/reference/source.md",
+ "markdownAbsoluteUrl": "https://leadtype.dev/docs/reference/source.md",
+ "relativePath": "reference/source",
+ "groups": [
+ "reference"
+ ],
+ "lastModified": "2026-05-13T06:50:54.987Z"
}
],
"navigation": {
@@ -274,21 +326,21 @@
],
"toc": [
{
- "id": "choose-your-path",
- "title": "Choose your path",
+ "id": "start-here",
+ "title": "Start here",
"level": 2,
"urlPath": "/docs",
- "urlWithHash": "/docs#choose-your-path",
- "absoluteUrlWithHash": "https://leadtype.dev/docs#choose-your-path",
+ "urlWithHash": "/docs#start-here",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs#start-here",
"children": []
},
{
- "id": "what-you-get",
- "title": "What you get",
+ "id": "what-leadtype-produces",
+ "title": "What leadtype produces",
"level": 2,
"urlPath": "/docs",
- "urlWithHash": "/docs#what-you-get",
- "absoluteUrlWithHash": "https://leadtype.dev/docs#what-you-get",
+ "urlWithHash": "/docs#what-leadtype-produces",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs#what-leadtype-produces",
"children": []
},
{
@@ -424,7 +476,7 @@
{
"urlPath": "/docs/quickstart",
"title": "Quickstart",
- "description": "Install leadtype, run the hosted-docs pipeline once, and inspect the generated artifacts.",
+ "description": "Install leadtype, author your first MDX page, and create a source. Then plug it into whatever framework you're using.",
"groups": [
"get-started"
],
@@ -448,21 +500,39 @@
"children": []
},
{
- "id": "generate-hosted-docs-output",
- "title": "Generate hosted docs output",
+ "id": "create-the-source",
+ "title": "Create the source",
+ "level": 2,
+ "urlPath": "/docs/quickstart",
+ "urlWithHash": "/docs/quickstart#create-the-source",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/quickstart#create-the-source",
+ "children": []
+ },
+ {
+ "id": "plug-it-into-your-framework",
+ "title": "Plug it into your framework",
+ "level": 2,
+ "urlPath": "/docs/quickstart",
+ "urlWithHash": "/docs/quickstart#plug-it-into-your-framework",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/quickstart#plug-it-into-your-framework",
+ "children": []
+ },
+ {
+ "id": "or-write-static-artifacts-to-disk",
+ "title": "Or: write static artifacts to disk",
"level": 2,
"urlPath": "/docs/quickstart",
- "urlWithHash": "/docs/quickstart#generate-hosted-docs-output",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/quickstart#generate-hosted-docs-output",
+ "urlWithHash": "/docs/quickstart#or-write-static-artifacts-to-disk",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/quickstart#or-write-static-artifacts-to-disk",
"children": []
},
{
- "id": "choose-the-next-setup-step",
- "title": "Choose the next setup step",
+ "id": "next-steps",
+ "title": "Next steps",
"level": 2,
"urlPath": "/docs/quickstart",
- "urlWithHash": "/docs/quickstart#choose-the-next-setup-step",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/quickstart#choose-the-next-setup-step",
+ "urlWithHash": "/docs/quickstart#next-steps",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/quickstart#next-steps",
"children": []
}
]
@@ -504,6 +574,15 @@
"absoluteUrlWithHash": "https://leadtype.dev/docs/authoring/components#the-naming-contract",
"children": []
},
+ {
+ "id": "reuse-shared-content",
+ "title": "Reuse shared content",
+ "level": 2,
+ "urlPath": "/docs/authoring/components",
+ "urlWithHash": "/docs/authoring/components#reuse-shared-content",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/authoring/components#reuse-shared-content",
+ "children": []
+ },
{
"id": "component-reference",
"title": "Component reference",
@@ -783,9 +862,64 @@
]
},
{
- "urlPath": "/docs/build/connect-docs-site",
- "title": "Connect a docs site",
- "description": "Build a shared docs app from source docs that live with the code they document.",
+ "urlPath": "/docs/build/build-a-docs-site",
+ "title": "Build a docs site",
+ "description": "Pick the right leadtype integration shape for your docs app, and what each path gives you.",
+ "groups": [
+ "docs-site"
+ ],
+ "toc": [
+ {
+ "id": "pick-your-path",
+ "title": "Pick your path",
+ "level": 2,
+ "urlPath": "/docs/build/build-a-docs-site",
+ "urlWithHash": "/docs/build/build-a-docs-site#pick-your-path",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/build-a-docs-site#pick-your-path",
+ "children": []
+ },
+ {
+ "id": "source-primitive-the-common-path",
+ "title": "Source primitive: the common path",
+ "level": 2,
+ "urlPath": "/docs/build/build-a-docs-site",
+ "urlWithHash": "/docs/build/build-a-docs-site#source-primitive-the-common-path",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/build-a-docs-site#source-primitive-the-common-path",
+ "children": []
+ },
+ {
+ "id": "static-artifacts-the-cli-path",
+ "title": "Static artifacts: the CLI path",
+ "level": 2,
+ "urlPath": "/docs/build/build-a-docs-site",
+ "urlWithHash": "/docs/build/build-a-docs-site#static-artifacts-the-cli-path",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/build-a-docs-site#static-artifacts-the-cli-path",
+ "children": []
+ },
+ {
+ "id": "add-the-cross-cutting-features",
+ "title": "Add the cross-cutting features",
+ "level": 2,
+ "urlPath": "/docs/build/build-a-docs-site",
+ "urlWithHash": "/docs/build/build-a-docs-site#add-the-cross-cutting-features",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/build-a-docs-site#add-the-cross-cutting-features",
+ "children": []
+ },
+ {
+ "id": "configure-product-and-groups",
+ "title": "Configure product and groups",
+ "level": 2,
+ "urlPath": "/docs/build/build-a-docs-site",
+ "urlWithHash": "/docs/build/build-a-docs-site#configure-product-and-groups",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/build-a-docs-site#configure-product-and-groups",
+ "children": []
+ }
+ ]
+ },
+ {
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "title": "Generate static artifacts",
+ "description": "Run leadtype generate from your build pipeline to write llms.txt, markdown mirrors, search index, sitemap, and agent-readability files to disk.",
"groups": [
"docs-site"
],
@@ -794,81 +928,145 @@
"id": "the-flow",
"title": "The flow",
"level": 2,
- "urlPath": "/docs/build/connect-docs-site",
- "urlWithHash": "/docs/build/connect-docs-site#the-flow",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/connect-docs-site#the-flow",
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "urlWithHash": "/docs/build/generate-static-artifacts#the-flow",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/generate-static-artifacts#the-flow",
"children": []
},
{
"id": "fetch-the-source-repo",
"title": "Fetch the source repo",
"level": 2,
- "urlPath": "/docs/build/connect-docs-site",
- "urlWithHash": "/docs/build/connect-docs-site#fetch-the-source-repo",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/connect-docs-site#fetch-the-source-repo",
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "urlWithHash": "/docs/build/generate-static-artifacts#fetch-the-source-repo",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/generate-static-artifacts#fetch-the-source-repo",
"children": []
},
{
"id": "lint-before-generate",
"title": "Lint before generate",
"level": 2,
- "urlPath": "/docs/build/connect-docs-site",
- "urlWithHash": "/docs/build/connect-docs-site#lint-before-generate",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/connect-docs-site#lint-before-generate",
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "urlWithHash": "/docs/build/generate-static-artifacts#lint-before-generate",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/generate-static-artifacts#lint-before-generate",
"children": []
},
{
- "id": "generate-hosted-artifacts",
- "title": "Generate hosted artifacts",
+ "id": "generate",
+ "title": "Generate",
"level": 2,
- "urlPath": "/docs/build/connect-docs-site",
- "urlWithHash": "/docs/build/connect-docs-site#generate-hosted-artifacts",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/connect-docs-site#generate-hosted-artifacts",
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "urlWithHash": "/docs/build/generate-static-artifacts#generate",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/generate-static-artifacts#generate",
"children": []
},
{
- "id": "wire-it-into-the-app-build",
- "title": "Wire it into the app build",
+ "id": "multi-source-mounting",
+ "title": "Multi-source mounting",
"level": 2,
- "urlPath": "/docs/build/connect-docs-site",
- "urlWithHash": "/docs/build/connect-docs-site#wire-it-into-the-app-build",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/connect-docs-site#wire-it-into-the-app-build",
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "urlWithHash": "/docs/build/generate-static-artifacts#multi-source-mounting",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/generate-static-artifacts#multi-source-mounting",
"children": []
},
{
- "id": "configure-product-and-groups",
- "title": "Configure product and groups",
+ "id": "wire-it-into-the-build",
+ "title": "Wire it into the build",
"level": 2,
- "urlPath": "/docs/build/connect-docs-site",
- "urlWithHash": "/docs/build/connect-docs-site#configure-product-and-groups",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/connect-docs-site#configure-product-and-groups",
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "urlWithHash": "/docs/build/generate-static-artifacts#wire-it-into-the-build",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/generate-static-artifacts#wire-it-into-the-build",
"children": []
},
{
- "id": "use-scripts-for-custom-pipelines",
- "title": "Use scripts for custom pipelines",
+ "id": "use-library-apis-for-custom-pipelines",
+ "title": "Use library APIs for custom pipelines",
"level": 2,
- "urlPath": "/docs/build/connect-docs-site",
- "urlWithHash": "/docs/build/connect-docs-site#use-scripts-for-custom-pipelines",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/connect-docs-site#use-scripts-for-custom-pipelines",
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "urlWithHash": "/docs/build/generate-static-artifacts#use-library-apis-for-custom-pipelines",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/generate-static-artifacts#use-library-apis-for-custom-pipelines",
"children": []
},
{
- "id": "wire-the-app-runtime",
- "title": "Wire the app runtime",
+ "id": "verify",
+ "title": "Verify",
+ "level": 2,
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "urlWithHash": "/docs/build/generate-static-artifacts#verify",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/generate-static-artifacts#verify",
+ "children": []
+ }
+ ]
+ },
+ {
+ "urlPath": "/docs/build/integrate-with-fumadocs",
+ "title": "Integrate with Fumadocs",
+ "description": "Wire leadtype's content layer into a fumadocs app for nav, search, and includes.",
+ "groups": [
+ "docs-site"
+ ],
+ "toc": [
+ {
+ "id": "tl-dr",
+ "title": "TL;DR",
"level": 2,
- "urlPath": "/docs/build/connect-docs-site",
- "urlWithHash": "/docs/build/connect-docs-site#wire-the-app-runtime",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/connect-docs-site#wire-the-app-runtime",
+ "urlPath": "/docs/build/integrate-with-fumadocs",
+ "urlWithHash": "/docs/build/integrate-with-fumadocs#tl-dr",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/integrate-with-fumadocs#tl-dr",
"children": []
},
{
- "id": "verify",
- "title": "Verify",
+ "id": "install",
+ "title": "Install",
+ "level": 2,
+ "urlPath": "/docs/build/integrate-with-fumadocs",
+ "urlWithHash": "/docs/build/integrate-with-fumadocs#install",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/integrate-with-fumadocs#install",
+ "children": []
+ },
+ {
+ "id": "wire-the-source",
+ "title": "Wire the source",
+ "level": 2,
+ "urlPath": "/docs/build/integrate-with-fumadocs",
+ "urlWithHash": "/docs/build/integrate-with-fumadocs#wire-the-source",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/integrate-with-fumadocs#wire-the-source",
+ "children": []
+ },
+ {
+ "id": "add-the-source-preset-to-your-mdx-compiler",
+ "title": "Add the source preset to your MDX compiler",
+ "level": 2,
+ "urlPath": "/docs/build/integrate-with-fumadocs",
+ "urlWithHash": "/docs/build/integrate-with-fumadocs#add-the-source-preset-to-your-mdx-compiler",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/integrate-with-fumadocs#add-the-source-preset-to-your-mdx-compiler",
+ "children": []
+ },
+ {
+ "id": "implement-the-tag-components",
+ "title": "Implement the tag components",
+ "level": 2,
+ "urlPath": "/docs/build/integrate-with-fumadocs",
+ "urlWithHash": "/docs/build/integrate-with-fumadocs#implement-the-tag-components",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/integrate-with-fumadocs#implement-the-tag-components",
+ "children": []
+ },
+ {
+ "id": "load-a-page-from-a-server-component",
+ "title": "Load a page from a server component",
+ "level": 2,
+ "urlPath": "/docs/build/integrate-with-fumadocs",
+ "urlWithHash": "/docs/build/integrate-with-fumadocs#load-a-page-from-a-server-component",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/integrate-with-fumadocs#load-a-page-from-a-server-component",
+ "children": []
+ },
+ {
+ "id": "add-search",
+ "title": "Add search",
"level": 2,
- "urlPath": "/docs/build/connect-docs-site",
- "urlWithHash": "/docs/build/connect-docs-site#verify",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/connect-docs-site#verify",
+ "urlPath": "/docs/build/integrate-with-fumadocs",
+ "urlWithHash": "/docs/build/integrate-with-fumadocs#add-search",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/integrate-with-fumadocs#add-search",
"children": []
}
]
@@ -966,56 +1164,147 @@
]
},
{
- "urlPath": "/docs/build/render-mdx-and-toc",
- "title": "Render MDX and TOC",
- "description": "Set up runtime MDX components, stable heading IDs, and a table of contents from the generated navigation manifest.",
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "title": "Use the source primitive",
+ "description": "Wire createDocsSource into Next, Astro, Vite, Nuxt, SvelteKit, or any MDX-aware bundler. Same primitive, multiple host shapes.",
"groups": [
"docs-site"
],
"toc": [
{
- "id": "register-mdx-components",
- "title": "Register MDX components",
+ "id": "tl-dr",
+ "title": "TL;DR",
+ "level": 2,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#tl-dr",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#tl-dr",
+ "children": []
+ },
+ {
+ "id": "install",
+ "title": "Install",
+ "level": 2,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#install",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#install",
+ "children": []
+ },
+ {
+ "id": "wire-into-your-framework",
+ "title": "Wire into your framework",
+ "level": 2,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#wire-into-your-framework",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#wire-into-your-framework",
+ "children": [
+ {
+ "id": "next-app-router",
+ "title": "Next App Router",
+ "level": 3,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#next-app-router",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#next-app-router",
+ "children": []
+ },
+ {
+ "id": "astro-content-collections",
+ "title": "Astro Content Collections",
+ "level": 3,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#astro-content-collections",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#astro-content-collections",
+ "children": []
+ },
+ {
+ "id": "vite-mdx-js-rollup-works-for-vue-solid-svelte-starters",
+ "title": "Vite + @mdx-js/rollup works for Vue, Solid, Svelte starters",
+ "level": 3,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#vite-mdx-js-rollup-works-for-vue-solid-svelte-starters",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#vite-mdx-js-rollup-works-for-vue-solid-svelte-starters",
+ "children": []
+ },
+ {
+ "id": "nuxt",
+ "title": "Nuxt",
+ "level": 3,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#nuxt",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#nuxt",
+ "children": []
+ },
+ {
+ "id": "sveltekit-mdsvex",
+ "title": "SvelteKit + mdsvex",
+ "level": 3,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#sveltekit-mdsvex",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#sveltekit-mdsvex",
+ "children": []
+ },
+ {
+ "id": "pattern-for-any-other-host",
+ "title": "Pattern for any other host",
+ "level": 3,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#pattern-for-any-other-host",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#pattern-for-any-other-host",
+ "children": []
+ }
+ ]
+ },
+ {
+ "id": "implement-the-tag-components",
+ "title": "Implement the tag components",
"level": 2,
- "urlPath": "/docs/build/render-mdx-and-toc",
- "urlWithHash": "/docs/build/render-mdx-and-toc#register-mdx-components",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/render-mdx-and-toc#register-mdx-components",
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#implement-the-tag-components",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#implement-the-tag-components",
"children": []
},
{
- "id": "use-the-same-heading-slugs",
- "title": "Use the same heading slugs",
+ "id": "build-the-sidebar-from-navigation",
+ "title": "Build the sidebar from navigation",
"level": 2,
- "urlPath": "/docs/build/render-mdx-and-toc",
- "urlWithHash": "/docs/build/render-mdx-and-toc#use-the-same-heading-slugs",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/render-mdx-and-toc#use-the-same-heading-slugs",
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#build-the-sidebar-from-navigation",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#build-the-sidebar-from-navigation",
"children": []
},
{
- "id": "generate-navigation-with-toc-data",
- "title": "Generate navigation with TOC data",
+ "id": "match-heading-slugs",
+ "title": "Match heading slugs",
"level": 2,
- "urlPath": "/docs/build/render-mdx-and-toc",
- "urlWithHash": "/docs/build/render-mdx-and-toc#generate-navigation-with-toc-data",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/render-mdx-and-toc#generate-navigation-with-toc-data",
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#match-heading-slugs",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#match-heading-slugs",
"children": []
},
{
- "id": "render-the-sidebar",
- "title": "Render the sidebar",
+ "id": "build-a-search-index",
+ "title": "Build a search index",
"level": 2,
- "urlPath": "/docs/build/render-mdx-and-toc",
- "urlWithHash": "/docs/build/render-mdx-and-toc#render-the-sidebar",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/render-mdx-and-toc#render-the-sidebar",
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#build-a-search-index",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#build-a-search-index",
"children": []
},
{
"id": "troubleshooting",
"title": "Troubleshooting",
"level": 2,
- "urlPath": "/docs/build/render-mdx-and-toc",
- "urlWithHash": "/docs/build/render-mdx-and-toc#troubleshooting",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/render-mdx-and-toc#troubleshooting",
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#troubleshooting",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#troubleshooting",
+ "children": []
+ },
+ {
+ "id": "reference",
+ "title": "Reference",
+ "level": 2,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#reference",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#reference",
"children": []
}
]
@@ -1222,6 +1511,15 @@
"absoluteUrlWithHash": "https://leadtype.dev/docs/reference/cli#config-loading",
"children": []
},
+ {
+ "id": "multiple-source-folders",
+ "title": "Multiple source folders",
+ "level": 3,
+ "urlPath": "/docs/reference/cli",
+ "urlWithHash": "/docs/reference/cli#multiple-source-folders",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/cli#multiple-source-folders",
+ "children": []
+ },
{
"id": "bundle-mode",
"title": "Bundle mode",
@@ -1546,6 +1844,15 @@
"absoluteUrlWithHash": "https://leadtype.dev/docs/reference/llm#typical-sequence",
"children": []
},
+ {
+ "id": "mounted-url-prefixes",
+ "title": "Mounted URL prefixes",
+ "level": 2,
+ "urlPath": "/docs/reference/llm",
+ "urlWithHash": "/docs/reference/llm#mounted-url-prefixes",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/llm#mounted-url-prefixes",
+ "children": []
+ },
{
"id": "generateagentreadabilityartifacts",
"title": "generateAgentReadabilityArtifacts",
@@ -1676,6 +1983,116 @@
}
]
},
+ {
+ "urlPath": "/docs/reference/mdx",
+ "title": "leadtype/mdx",
+ "description": "Tag type contracts and the build-time source preset for consumers rendering MDX themselves.",
+ "groups": [
+ "reference"
+ ],
+ "toc": [
+ {
+ "id": "the-mdx-source-preset",
+ "title": "The MDX-source preset",
+ "level": 2,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#the-mdx-source-preset",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#the-mdx-source-preset",
+ "children": []
+ },
+ {
+ "id": "framework-neutral-by-design",
+ "title": "Framework-neutral by design",
+ "level": 2,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#framework-neutral-by-design",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#framework-neutral-by-design",
+ "children": [
+ {
+ "id": "react",
+ "title": "React",
+ "level": 3,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#react",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#react",
+ "children": []
+ },
+ {
+ "id": "vue",
+ "title": "Vue",
+ "level": 3,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#vue",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#vue",
+ "children": []
+ },
+ {
+ "id": "svelte",
+ "title": "Svelte",
+ "level": 3,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#svelte",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#svelte",
+ "children": []
+ },
+ {
+ "id": "solid",
+ "title": "Solid",
+ "level": 3,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#solid",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#solid",
+ "children": []
+ },
+ {
+ "id": "astro",
+ "title": "Astro",
+ "level": 3,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#astro",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#astro",
+ "children": []
+ },
+ {
+ "id": "full-type-inventory",
+ "title": "Full type inventory",
+ "level": 3,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#full-type-inventory",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#full-type-inventory",
+ "children": []
+ },
+ {
+ "id": "build-time-only",
+ "title": "Build-time only:",
+ "level": 3,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#build-time-only",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#build-time-only",
+ "children": []
+ }
+ ]
+ },
+ {
+ "id": "include-resolution",
+ "title": "Include resolution",
+ "level": 2,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#include-resolution",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#include-resolution",
+ "children": []
+ },
+ {
+ "id": "re-exported-path-helpers",
+ "title": "Re-exported path helpers",
+ "level": 2,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#re-exported-path-helpers",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#re-exported-path-helpers",
+ "children": []
+ }
+ ]
+ },
{
"urlPath": "/docs/reference/remark",
"title": "Remark plugins",
@@ -1831,6 +2248,162 @@
"children": []
}
]
+ },
+ {
+ "urlPath": "/docs/reference/source",
+ "title": "createDocsSource",
+ "description": "Framework-neutral docs source primitive — navigation, page loader, search index, and include resolver.",
+ "groups": [
+ "reference"
+ ],
+ "toc": [
+ {
+ "id": "configuration",
+ "title": "Configuration",
+ "level": 2,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#configuration",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#configuration",
+ "children": []
+ },
+ {
+ "id": "source-methods",
+ "title": "Source methods",
+ "level": 2,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#source-methods",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#source-methods",
+ "children": [
+ {
+ "id": "getnavigation-promise",
+ "title": "getNavigation : Promise",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#getnavigation-promise",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#getnavigation-promise",
+ "children": []
+ },
+ {
+ "id": "listpages-promise",
+ "title": "listPages : Promise",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#listpages-promise",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#listpages-promise",
+ "children": []
+ },
+ {
+ "id": "loadpage-slug-promise",
+ "title": "loadPage slug : Promise",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#loadpage-slug-promise",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#loadpage-slug-promise",
+ "children": []
+ },
+ {
+ "id": "buildsearchindex-promise",
+ "title": "buildSearchIndex : Promise",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#buildsearchindex-promise",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#buildsearchindex-promise",
+ "children": []
+ },
+ {
+ "id": "resolveinclude-specifier-options-promise",
+ "title": "resolveInclude specifier, options? : Promise",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#resolveinclude-specifier-options-promise",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#resolveinclude-specifier-options-promise",
+ "children": []
+ }
+ ]
+ },
+ {
+ "id": "choosing-between-loadpage-and-direct-mdx-imports",
+ "title": "Choosing between loadPage and direct .mdx imports",
+ "level": 2,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#choosing-between-loadpage-and-direct-mdx-imports",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#choosing-between-loadpage-and-direct-mdx-imports",
+ "children": []
+ },
+ {
+ "id": "framework-integrations",
+ "title": "Framework integrations",
+ "level": 2,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#framework-integrations",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#framework-integrations",
+ "children": [
+ {
+ "id": "next-app-router",
+ "title": "Next App Router",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#next-app-router",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#next-app-router",
+ "children": []
+ },
+ {
+ "id": "astro-content-collections",
+ "title": "Astro Content Collections",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#astro-content-collections",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#astro-content-collections",
+ "children": []
+ },
+ {
+ "id": "vite-mdx-js-rollup-works-for-vue-solid-svelte-starters",
+ "title": "Vite + @mdx-js/rollup works for Vue, Solid, Svelte starters",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#vite-mdx-js-rollup-works-for-vue-solid-svelte-starters",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#vite-mdx-js-rollup-works-for-vue-solid-svelte-starters",
+ "children": []
+ },
+ {
+ "id": "nuxt",
+ "title": "Nuxt",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#nuxt",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#nuxt",
+ "children": []
+ },
+ {
+ "id": "sveltekit-mdsvex",
+ "title": "SvelteKit + mdsvex",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#sveltekit-mdsvex",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#sveltekit-mdsvex",
+ "children": []
+ },
+ {
+ "id": "fumadocs",
+ "title": "Fumadocs",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#fumadocs",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#fumadocs",
+ "children": []
+ },
+ {
+ "id": "pattern-for-any-other-framework",
+ "title": "Pattern for any other framework",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#pattern-for-any-other-framework",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#pattern-for-any-other-framework",
+ "children": []
+ }
+ ]
+ }
+ ]
}
],
"children": []
diff --git a/apps/example/src/generated/docs-nav.json b/apps/example/src/generated/docs-nav.json
index 739df60..8d3e8cb 100644
--- a/apps/example/src/generated/docs-nav.json
+++ b/apps/example/src/generated/docs-nav.json
@@ -17,21 +17,21 @@
],
"toc": [
{
- "id": "choose-your-path",
- "title": "Choose your path",
+ "id": "start-here",
+ "title": "Start here",
"level": 2,
"urlPath": "/docs",
- "urlWithHash": "/docs#choose-your-path",
- "absoluteUrlWithHash": "https://leadtype.dev/docs#choose-your-path",
+ "urlWithHash": "/docs#start-here",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs#start-here",
"children": []
},
{
- "id": "what-you-get",
- "title": "What you get",
+ "id": "what-leadtype-produces",
+ "title": "What leadtype produces",
"level": 2,
"urlPath": "/docs",
- "urlWithHash": "/docs#what-you-get",
- "absoluteUrlWithHash": "https://leadtype.dev/docs#what-you-get",
+ "urlWithHash": "/docs#what-leadtype-produces",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs#what-leadtype-produces",
"children": []
},
{
@@ -167,7 +167,7 @@
{
"urlPath": "/docs/quickstart",
"title": "Quickstart",
- "description": "Install leadtype, run the hosted-docs pipeline once, and inspect the generated artifacts.",
+ "description": "Install leadtype, author your first MDX page, and create a source. Then plug it into whatever framework you're using.",
"groups": [
"get-started"
],
@@ -191,21 +191,39 @@
"children": []
},
{
- "id": "generate-hosted-docs-output",
- "title": "Generate hosted docs output",
+ "id": "create-the-source",
+ "title": "Create the source",
"level": 2,
"urlPath": "/docs/quickstart",
- "urlWithHash": "/docs/quickstart#generate-hosted-docs-output",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/quickstart#generate-hosted-docs-output",
+ "urlWithHash": "/docs/quickstart#create-the-source",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/quickstart#create-the-source",
"children": []
},
{
- "id": "choose-the-next-setup-step",
- "title": "Choose the next setup step",
+ "id": "plug-it-into-your-framework",
+ "title": "Plug it into your framework",
"level": 2,
"urlPath": "/docs/quickstart",
- "urlWithHash": "/docs/quickstart#choose-the-next-setup-step",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/quickstart#choose-the-next-setup-step",
+ "urlWithHash": "/docs/quickstart#plug-it-into-your-framework",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/quickstart#plug-it-into-your-framework",
+ "children": []
+ },
+ {
+ "id": "or-write-static-artifacts-to-disk",
+ "title": "Or: write static artifacts to disk",
+ "level": 2,
+ "urlPath": "/docs/quickstart",
+ "urlWithHash": "/docs/quickstart#or-write-static-artifacts-to-disk",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/quickstart#or-write-static-artifacts-to-disk",
+ "children": []
+ },
+ {
+ "id": "next-steps",
+ "title": "Next steps",
+ "level": 2,
+ "urlPath": "/docs/quickstart",
+ "urlWithHash": "/docs/quickstart#next-steps",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/quickstart#next-steps",
"children": []
}
]
@@ -247,6 +265,15 @@
"absoluteUrlWithHash": "https://leadtype.dev/docs/authoring/components#the-naming-contract",
"children": []
},
+ {
+ "id": "reuse-shared-content",
+ "title": "Reuse shared content",
+ "level": 2,
+ "urlPath": "/docs/authoring/components",
+ "urlWithHash": "/docs/authoring/components#reuse-shared-content",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/authoring/components#reuse-shared-content",
+ "children": []
+ },
{
"id": "component-reference",
"title": "Component reference",
@@ -462,73 +489,283 @@
"description": "Generate hosted docs artifacts, wire them into an app, add search, and make pages agent-readable.",
"pages": [
{
- "urlPath": "/docs/build/add-search",
- "title": "Add search",
- "description": "Generate a static docs search index, query it at runtime, and optionally stream source-grounded answers.",
+ "urlPath": "/docs/build/build-a-docs-site",
+ "title": "Build a docs site",
+ "description": "Pick the right leadtype integration shape for your docs app, and what each path gives you.",
"groups": [
"docs-site"
],
"toc": [
{
- "id": "generate-the-files",
- "title": "Generate the files",
+ "id": "pick-your-path",
+ "title": "Pick your path",
"level": 2,
- "urlPath": "/docs/build/add-search",
- "urlWithHash": "/docs/build/add-search#generate-the-files",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/add-search#generate-the-files",
+ "urlPath": "/docs/build/build-a-docs-site",
+ "urlWithHash": "/docs/build/build-a-docs-site#pick-your-path",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/build-a-docs-site#pick-your-path",
"children": []
},
{
- "id": "query-at-runtime",
- "title": "Query at runtime",
+ "id": "source-primitive-the-common-path",
+ "title": "Source primitive: the common path",
"level": 2,
- "urlPath": "/docs/build/add-search",
- "urlWithHash": "/docs/build/add-search#query-at-runtime",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/add-search#query-at-runtime",
+ "urlPath": "/docs/build/build-a-docs-site",
+ "urlWithHash": "/docs/build/build-a-docs-site#source-primitive-the-common-path",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/build-a-docs-site#source-primitive-the-common-path",
"children": []
},
{
- "id": "add-vocabulary-aliases",
- "title": "Add vocabulary aliases",
+ "id": "static-artifacts-the-cli-path",
+ "title": "Static artifacts: the CLI path",
"level": 2,
- "urlPath": "/docs/build/add-search",
- "urlWithHash": "/docs/build/add-search#add-vocabulary-aliases",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/add-search#add-vocabulary-aliases",
+ "urlPath": "/docs/build/build-a-docs-site",
+ "urlWithHash": "/docs/build/build-a-docs-site#static-artifacts-the-cli-path",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/build-a-docs-site#static-artifacts-the-cli-path",
"children": []
},
{
- "id": "optional-ai-answers",
- "title": "Optional AI answers",
+ "id": "add-the-cross-cutting-features",
+ "title": "Add the cross-cutting features",
"level": 2,
- "urlPath": "/docs/build/add-search",
- "urlWithHash": "/docs/build/add-search#optional-ai-answers",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/add-search#optional-ai-answers",
+ "urlPath": "/docs/build/build-a-docs-site",
+ "urlWithHash": "/docs/build/build-a-docs-site#add-the-cross-cutting-features",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/build-a-docs-site#add-the-cross-cutting-features",
"children": []
},
{
- "id": "guard-the-endpoint",
- "title": "Guard the endpoint",
+ "id": "configure-product-and-groups",
+ "title": "Configure product and groups",
"level": 2,
- "urlPath": "/docs/build/add-search",
- "urlWithHash": "/docs/build/add-search#guard-the-endpoint",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/add-search#guard-the-endpoint",
+ "urlPath": "/docs/build/build-a-docs-site",
+ "urlWithHash": "/docs/build/build-a-docs-site#configure-product-and-groups",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/build-a-docs-site#configure-product-and-groups",
+ "children": []
+ }
+ ]
+ },
+ {
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "title": "Use the source primitive",
+ "description": "Wire createDocsSource into Next, Astro, Vite, Nuxt, SvelteKit, or any MDX-aware bundler. Same primitive, multiple host shapes.",
+ "groups": [
+ "docs-site"
+ ],
+ "toc": [
+ {
+ "id": "tl-dr",
+ "title": "TL;DR",
+ "level": 2,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#tl-dr",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#tl-dr",
"children": []
},
{
- "id": "verify",
- "title": "Verify",
+ "id": "install",
+ "title": "Install",
"level": 2,
- "urlPath": "/docs/build/add-search",
- "urlWithHash": "/docs/build/add-search#verify",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/add-search#verify",
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#install",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#install",
+ "children": []
+ },
+ {
+ "id": "wire-into-your-framework",
+ "title": "Wire into your framework",
+ "level": 2,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#wire-into-your-framework",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#wire-into-your-framework",
+ "children": [
+ {
+ "id": "next-app-router",
+ "title": "Next App Router",
+ "level": 3,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#next-app-router",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#next-app-router",
+ "children": []
+ },
+ {
+ "id": "astro-content-collections",
+ "title": "Astro Content Collections",
+ "level": 3,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#astro-content-collections",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#astro-content-collections",
+ "children": []
+ },
+ {
+ "id": "vite-mdx-js-rollup-works-for-vue-solid-svelte-starters",
+ "title": "Vite + @mdx-js/rollup works for Vue, Solid, Svelte starters",
+ "level": 3,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#vite-mdx-js-rollup-works-for-vue-solid-svelte-starters",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#vite-mdx-js-rollup-works-for-vue-solid-svelte-starters",
+ "children": []
+ },
+ {
+ "id": "nuxt",
+ "title": "Nuxt",
+ "level": 3,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#nuxt",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#nuxt",
+ "children": []
+ },
+ {
+ "id": "sveltekit-mdsvex",
+ "title": "SvelteKit + mdsvex",
+ "level": 3,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#sveltekit-mdsvex",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#sveltekit-mdsvex",
+ "children": []
+ },
+ {
+ "id": "pattern-for-any-other-host",
+ "title": "Pattern for any other host",
+ "level": 3,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#pattern-for-any-other-host",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#pattern-for-any-other-host",
+ "children": []
+ }
+ ]
+ },
+ {
+ "id": "implement-the-tag-components",
+ "title": "Implement the tag components",
+ "level": 2,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#implement-the-tag-components",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#implement-the-tag-components",
+ "children": []
+ },
+ {
+ "id": "build-the-sidebar-from-navigation",
+ "title": "Build the sidebar from navigation",
+ "level": 2,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#build-the-sidebar-from-navigation",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#build-the-sidebar-from-navigation",
+ "children": []
+ },
+ {
+ "id": "match-heading-slugs",
+ "title": "Match heading slugs",
+ "level": 2,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#match-heading-slugs",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#match-heading-slugs",
+ "children": []
+ },
+ {
+ "id": "build-a-search-index",
+ "title": "Build a search index",
+ "level": 2,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#build-a-search-index",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#build-a-search-index",
+ "children": []
+ },
+ {
+ "id": "troubleshooting",
+ "title": "Troubleshooting",
+ "level": 2,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#troubleshooting",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#troubleshooting",
+ "children": []
+ },
+ {
+ "id": "reference",
+ "title": "Reference",
+ "level": 2,
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "urlWithHash": "/docs/build/use-the-source-primitive#reference",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/use-the-source-primitive#reference",
+ "children": []
+ }
+ ]
+ },
+ {
+ "urlPath": "/docs/build/integrate-with-fumadocs",
+ "title": "Integrate with Fumadocs",
+ "description": "Wire leadtype's content layer into a fumadocs app for nav, search, and includes.",
+ "groups": [
+ "docs-site"
+ ],
+ "toc": [
+ {
+ "id": "tl-dr",
+ "title": "TL;DR",
+ "level": 2,
+ "urlPath": "/docs/build/integrate-with-fumadocs",
+ "urlWithHash": "/docs/build/integrate-with-fumadocs#tl-dr",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/integrate-with-fumadocs#tl-dr",
+ "children": []
+ },
+ {
+ "id": "install",
+ "title": "Install",
+ "level": 2,
+ "urlPath": "/docs/build/integrate-with-fumadocs",
+ "urlWithHash": "/docs/build/integrate-with-fumadocs#install",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/integrate-with-fumadocs#install",
+ "children": []
+ },
+ {
+ "id": "wire-the-source",
+ "title": "Wire the source",
+ "level": 2,
+ "urlPath": "/docs/build/integrate-with-fumadocs",
+ "urlWithHash": "/docs/build/integrate-with-fumadocs#wire-the-source",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/integrate-with-fumadocs#wire-the-source",
+ "children": []
+ },
+ {
+ "id": "add-the-source-preset-to-your-mdx-compiler",
+ "title": "Add the source preset to your MDX compiler",
+ "level": 2,
+ "urlPath": "/docs/build/integrate-with-fumadocs",
+ "urlWithHash": "/docs/build/integrate-with-fumadocs#add-the-source-preset-to-your-mdx-compiler",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/integrate-with-fumadocs#add-the-source-preset-to-your-mdx-compiler",
+ "children": []
+ },
+ {
+ "id": "implement-the-tag-components",
+ "title": "Implement the tag components",
+ "level": 2,
+ "urlPath": "/docs/build/integrate-with-fumadocs",
+ "urlWithHash": "/docs/build/integrate-with-fumadocs#implement-the-tag-components",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/integrate-with-fumadocs#implement-the-tag-components",
+ "children": []
+ },
+ {
+ "id": "load-a-page-from-a-server-component",
+ "title": "Load a page from a server component",
+ "level": 2,
+ "urlPath": "/docs/build/integrate-with-fumadocs",
+ "urlWithHash": "/docs/build/integrate-with-fumadocs#load-a-page-from-a-server-component",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/integrate-with-fumadocs#load-a-page-from-a-server-component",
+ "children": []
+ },
+ {
+ "id": "add-search",
+ "title": "Add search",
+ "level": 2,
+ "urlPath": "/docs/build/integrate-with-fumadocs",
+ "urlWithHash": "/docs/build/integrate-with-fumadocs#add-search",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/integrate-with-fumadocs#add-search",
"children": []
}
]
},
{
- "urlPath": "/docs/build/connect-docs-site",
- "title": "Connect a docs site",
- "description": "Build a shared docs app from source docs that live with the code they document.",
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "title": "Generate static artifacts",
+ "description": "Run leadtype generate from your build pipeline to write llms.txt, markdown mirrors, search index, sitemap, and agent-readability files to disk.",
"groups": [
"docs-site"
],
@@ -537,81 +774,72 @@
"id": "the-flow",
"title": "The flow",
"level": 2,
- "urlPath": "/docs/build/connect-docs-site",
- "urlWithHash": "/docs/build/connect-docs-site#the-flow",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/connect-docs-site#the-flow",
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "urlWithHash": "/docs/build/generate-static-artifacts#the-flow",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/generate-static-artifacts#the-flow",
"children": []
},
{
"id": "fetch-the-source-repo",
"title": "Fetch the source repo",
"level": 2,
- "urlPath": "/docs/build/connect-docs-site",
- "urlWithHash": "/docs/build/connect-docs-site#fetch-the-source-repo",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/connect-docs-site#fetch-the-source-repo",
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "urlWithHash": "/docs/build/generate-static-artifacts#fetch-the-source-repo",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/generate-static-artifacts#fetch-the-source-repo",
"children": []
},
{
"id": "lint-before-generate",
"title": "Lint before generate",
"level": 2,
- "urlPath": "/docs/build/connect-docs-site",
- "urlWithHash": "/docs/build/connect-docs-site#lint-before-generate",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/connect-docs-site#lint-before-generate",
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "urlWithHash": "/docs/build/generate-static-artifacts#lint-before-generate",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/generate-static-artifacts#lint-before-generate",
"children": []
},
{
- "id": "generate-hosted-artifacts",
- "title": "Generate hosted artifacts",
- "level": 2,
- "urlPath": "/docs/build/connect-docs-site",
- "urlWithHash": "/docs/build/connect-docs-site#generate-hosted-artifacts",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/connect-docs-site#generate-hosted-artifacts",
- "children": []
- },
- {
- "id": "wire-it-into-the-app-build",
- "title": "Wire it into the app build",
+ "id": "generate",
+ "title": "Generate",
"level": 2,
- "urlPath": "/docs/build/connect-docs-site",
- "urlWithHash": "/docs/build/connect-docs-site#wire-it-into-the-app-build",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/connect-docs-site#wire-it-into-the-app-build",
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "urlWithHash": "/docs/build/generate-static-artifacts#generate",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/generate-static-artifacts#generate",
"children": []
},
{
- "id": "configure-product-and-groups",
- "title": "Configure product and groups",
+ "id": "multi-source-mounting",
+ "title": "Multi-source mounting",
"level": 2,
- "urlPath": "/docs/build/connect-docs-site",
- "urlWithHash": "/docs/build/connect-docs-site#configure-product-and-groups",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/connect-docs-site#configure-product-and-groups",
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "urlWithHash": "/docs/build/generate-static-artifacts#multi-source-mounting",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/generate-static-artifacts#multi-source-mounting",
"children": []
},
{
- "id": "use-scripts-for-custom-pipelines",
- "title": "Use scripts for custom pipelines",
+ "id": "wire-it-into-the-build",
+ "title": "Wire it into the build",
"level": 2,
- "urlPath": "/docs/build/connect-docs-site",
- "urlWithHash": "/docs/build/connect-docs-site#use-scripts-for-custom-pipelines",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/connect-docs-site#use-scripts-for-custom-pipelines",
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "urlWithHash": "/docs/build/generate-static-artifacts#wire-it-into-the-build",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/generate-static-artifacts#wire-it-into-the-build",
"children": []
},
{
- "id": "wire-the-app-runtime",
- "title": "Wire the app runtime",
+ "id": "use-library-apis-for-custom-pipelines",
+ "title": "Use library APIs for custom pipelines",
"level": 2,
- "urlPath": "/docs/build/connect-docs-site",
- "urlWithHash": "/docs/build/connect-docs-site#wire-the-app-runtime",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/connect-docs-site#wire-the-app-runtime",
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "urlWithHash": "/docs/build/generate-static-artifacts#use-library-apis-for-custom-pipelines",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/generate-static-artifacts#use-library-apis-for-custom-pipelines",
"children": []
},
{
"id": "verify",
"title": "Verify",
"level": 2,
- "urlPath": "/docs/build/connect-docs-site",
- "urlWithHash": "/docs/build/connect-docs-site#verify",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/connect-docs-site#verify",
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "urlWithHash": "/docs/build/generate-static-artifacts#verify",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/generate-static-artifacts#verify",
"children": []
}
]
@@ -709,56 +937,65 @@
]
},
{
- "urlPath": "/docs/build/render-mdx-and-toc",
- "title": "Render MDX and TOC",
- "description": "Set up runtime MDX components, stable heading IDs, and a table of contents from the generated navigation manifest.",
+ "urlPath": "/docs/build/add-search",
+ "title": "Add search",
+ "description": "Generate a static docs search index, query it at runtime, and optionally stream source-grounded answers.",
"groups": [
"docs-site"
],
"toc": [
{
- "id": "register-mdx-components",
- "title": "Register MDX components",
+ "id": "generate-the-files",
+ "title": "Generate the files",
+ "level": 2,
+ "urlPath": "/docs/build/add-search",
+ "urlWithHash": "/docs/build/add-search#generate-the-files",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/add-search#generate-the-files",
+ "children": []
+ },
+ {
+ "id": "query-at-runtime",
+ "title": "Query at runtime",
"level": 2,
- "urlPath": "/docs/build/render-mdx-and-toc",
- "urlWithHash": "/docs/build/render-mdx-and-toc#register-mdx-components",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/render-mdx-and-toc#register-mdx-components",
+ "urlPath": "/docs/build/add-search",
+ "urlWithHash": "/docs/build/add-search#query-at-runtime",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/add-search#query-at-runtime",
"children": []
},
{
- "id": "use-the-same-heading-slugs",
- "title": "Use the same heading slugs",
+ "id": "add-vocabulary-aliases",
+ "title": "Add vocabulary aliases",
"level": 2,
- "urlPath": "/docs/build/render-mdx-and-toc",
- "urlWithHash": "/docs/build/render-mdx-and-toc#use-the-same-heading-slugs",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/render-mdx-and-toc#use-the-same-heading-slugs",
+ "urlPath": "/docs/build/add-search",
+ "urlWithHash": "/docs/build/add-search#add-vocabulary-aliases",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/add-search#add-vocabulary-aliases",
"children": []
},
{
- "id": "generate-navigation-with-toc-data",
- "title": "Generate navigation with TOC data",
+ "id": "optional-ai-answers",
+ "title": "Optional AI answers",
"level": 2,
- "urlPath": "/docs/build/render-mdx-and-toc",
- "urlWithHash": "/docs/build/render-mdx-and-toc#generate-navigation-with-toc-data",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/render-mdx-and-toc#generate-navigation-with-toc-data",
+ "urlPath": "/docs/build/add-search",
+ "urlWithHash": "/docs/build/add-search#optional-ai-answers",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/add-search#optional-ai-answers",
"children": []
},
{
- "id": "render-the-sidebar",
- "title": "Render the sidebar",
+ "id": "guard-the-endpoint",
+ "title": "Guard the endpoint",
"level": 2,
- "urlPath": "/docs/build/render-mdx-and-toc",
- "urlWithHash": "/docs/build/render-mdx-and-toc#render-the-sidebar",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/render-mdx-and-toc#render-the-sidebar",
+ "urlPath": "/docs/build/add-search",
+ "urlWithHash": "/docs/build/add-search#guard-the-endpoint",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/add-search#guard-the-endpoint",
"children": []
},
{
- "id": "troubleshooting",
- "title": "Troubleshooting",
+ "id": "verify",
+ "title": "Verify",
"level": 2,
- "urlPath": "/docs/build/render-mdx-and-toc",
- "urlWithHash": "/docs/build/render-mdx-and-toc#troubleshooting",
- "absoluteUrlWithHash": "https://leadtype.dev/docs/build/render-mdx-and-toc#troubleshooting",
+ "urlPath": "/docs/build/add-search",
+ "urlWithHash": "/docs/build/add-search#verify",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/build/add-search#verify",
"children": []
}
]
@@ -965,6 +1202,15 @@
"absoluteUrlWithHash": "https://leadtype.dev/docs/reference/cli#config-loading",
"children": []
},
+ {
+ "id": "multiple-source-folders",
+ "title": "Multiple source folders",
+ "level": 3,
+ "urlPath": "/docs/reference/cli",
+ "urlWithHash": "/docs/reference/cli#multiple-source-folders",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/cli#multiple-source-folders",
+ "children": []
+ },
{
"id": "bundle-mode",
"title": "Bundle mode",
@@ -1289,6 +1535,15 @@
"absoluteUrlWithHash": "https://leadtype.dev/docs/reference/llm#typical-sequence",
"children": []
},
+ {
+ "id": "mounted-url-prefixes",
+ "title": "Mounted URL prefixes",
+ "level": 2,
+ "urlPath": "/docs/reference/llm",
+ "urlWithHash": "/docs/reference/llm#mounted-url-prefixes",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/llm#mounted-url-prefixes",
+ "children": []
+ },
{
"id": "generateagentreadabilityartifacts",
"title": "generateAgentReadabilityArtifacts",
@@ -1419,6 +1674,116 @@
}
]
},
+ {
+ "urlPath": "/docs/reference/mdx",
+ "title": "leadtype/mdx",
+ "description": "Tag type contracts and the build-time source preset for consumers rendering MDX themselves.",
+ "groups": [
+ "reference"
+ ],
+ "toc": [
+ {
+ "id": "the-mdx-source-preset",
+ "title": "The MDX-source preset",
+ "level": 2,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#the-mdx-source-preset",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#the-mdx-source-preset",
+ "children": []
+ },
+ {
+ "id": "framework-neutral-by-design",
+ "title": "Framework-neutral by design",
+ "level": 2,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#framework-neutral-by-design",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#framework-neutral-by-design",
+ "children": [
+ {
+ "id": "react",
+ "title": "React",
+ "level": 3,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#react",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#react",
+ "children": []
+ },
+ {
+ "id": "vue",
+ "title": "Vue",
+ "level": 3,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#vue",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#vue",
+ "children": []
+ },
+ {
+ "id": "svelte",
+ "title": "Svelte",
+ "level": 3,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#svelte",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#svelte",
+ "children": []
+ },
+ {
+ "id": "solid",
+ "title": "Solid",
+ "level": 3,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#solid",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#solid",
+ "children": []
+ },
+ {
+ "id": "astro",
+ "title": "Astro",
+ "level": 3,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#astro",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#astro",
+ "children": []
+ },
+ {
+ "id": "full-type-inventory",
+ "title": "Full type inventory",
+ "level": 3,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#full-type-inventory",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#full-type-inventory",
+ "children": []
+ },
+ {
+ "id": "build-time-only",
+ "title": "Build-time only:",
+ "level": 3,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#build-time-only",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#build-time-only",
+ "children": []
+ }
+ ]
+ },
+ {
+ "id": "include-resolution",
+ "title": "Include resolution",
+ "level": 2,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#include-resolution",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#include-resolution",
+ "children": []
+ },
+ {
+ "id": "re-exported-path-helpers",
+ "title": "Re-exported path helpers",
+ "level": 2,
+ "urlPath": "/docs/reference/mdx",
+ "urlWithHash": "/docs/reference/mdx#re-exported-path-helpers",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/mdx#re-exported-path-helpers",
+ "children": []
+ }
+ ]
+ },
{
"urlPath": "/docs/reference/remark",
"title": "Remark plugins",
@@ -1574,6 +1939,162 @@
"children": []
}
]
+ },
+ {
+ "urlPath": "/docs/reference/source",
+ "title": "createDocsSource",
+ "description": "Framework-neutral docs source primitive — navigation, page loader, search index, and include resolver.",
+ "groups": [
+ "reference"
+ ],
+ "toc": [
+ {
+ "id": "configuration",
+ "title": "Configuration",
+ "level": 2,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#configuration",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#configuration",
+ "children": []
+ },
+ {
+ "id": "source-methods",
+ "title": "Source methods",
+ "level": 2,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#source-methods",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#source-methods",
+ "children": [
+ {
+ "id": "getnavigation-promise",
+ "title": "getNavigation : Promise",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#getnavigation-promise",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#getnavigation-promise",
+ "children": []
+ },
+ {
+ "id": "listpages-promise",
+ "title": "listPages : Promise",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#listpages-promise",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#listpages-promise",
+ "children": []
+ },
+ {
+ "id": "loadpage-slug-promise",
+ "title": "loadPage slug : Promise",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#loadpage-slug-promise",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#loadpage-slug-promise",
+ "children": []
+ },
+ {
+ "id": "buildsearchindex-promise",
+ "title": "buildSearchIndex : Promise",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#buildsearchindex-promise",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#buildsearchindex-promise",
+ "children": []
+ },
+ {
+ "id": "resolveinclude-specifier-options-promise",
+ "title": "resolveInclude specifier, options? : Promise",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#resolveinclude-specifier-options-promise",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#resolveinclude-specifier-options-promise",
+ "children": []
+ }
+ ]
+ },
+ {
+ "id": "choosing-between-loadpage-and-direct-mdx-imports",
+ "title": "Choosing between loadPage and direct .mdx imports",
+ "level": 2,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#choosing-between-loadpage-and-direct-mdx-imports",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#choosing-between-loadpage-and-direct-mdx-imports",
+ "children": []
+ },
+ {
+ "id": "framework-integrations",
+ "title": "Framework integrations",
+ "level": 2,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#framework-integrations",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#framework-integrations",
+ "children": [
+ {
+ "id": "next-app-router",
+ "title": "Next App Router",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#next-app-router",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#next-app-router",
+ "children": []
+ },
+ {
+ "id": "astro-content-collections",
+ "title": "Astro Content Collections",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#astro-content-collections",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#astro-content-collections",
+ "children": []
+ },
+ {
+ "id": "vite-mdx-js-rollup-works-for-vue-solid-svelte-starters",
+ "title": "Vite + @mdx-js/rollup works for Vue, Solid, Svelte starters",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#vite-mdx-js-rollup-works-for-vue-solid-svelte-starters",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#vite-mdx-js-rollup-works-for-vue-solid-svelte-starters",
+ "children": []
+ },
+ {
+ "id": "nuxt",
+ "title": "Nuxt",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#nuxt",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#nuxt",
+ "children": []
+ },
+ {
+ "id": "sveltekit-mdsvex",
+ "title": "SvelteKit + mdsvex",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#sveltekit-mdsvex",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#sveltekit-mdsvex",
+ "children": []
+ },
+ {
+ "id": "fumadocs",
+ "title": "Fumadocs",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#fumadocs",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#fumadocs",
+ "children": []
+ },
+ {
+ "id": "pattern-for-any-other-framework",
+ "title": "Pattern for any other framework",
+ "level": 3,
+ "urlPath": "/docs/reference/source",
+ "urlWithHash": "/docs/reference/source#pattern-for-any-other-framework",
+ "absoluteUrlWithHash": "https://leadtype.dev/docs/reference/source#pattern-for-any-other-framework",
+ "children": []
+ }
+ ]
+ }
+ ]
}
],
"children": []
diff --git a/apps/example/src/generated/docs-pages.json b/apps/example/src/generated/docs-pages.json
new file mode 100644
index 0000000..1373be4
--- /dev/null
+++ b/apps/example/src/generated/docs-pages.json
@@ -0,0 +1,341 @@
+[
+ {
+ "slug": [
+ "authoring",
+ "components"
+ ],
+ "urlPath": "/docs/authoring/components",
+ "title": "Components",
+ "description": "MDX components the pipeline knows how to flatten into agent-readable markdown.",
+ "relativePath": "authoring/components",
+ "extension": ".mdx",
+ "groups": [
+ "authoring"
+ ],
+ "globKey": "../../../../../docs/authoring/components.mdx"
+ },
+ {
+ "slug": [
+ "authoring",
+ "frontmatter"
+ ],
+ "urlPath": "/docs/authoring/frontmatter",
+ "title": "Frontmatter",
+ "description": "Required fields, group semantics, and how authored MDX becomes a navigation tree.",
+ "relativePath": "authoring/frontmatter",
+ "extension": ".mdx",
+ "groups": [
+ "authoring"
+ ],
+ "globKey": "../../../../../docs/authoring/frontmatter.mdx"
+ },
+ {
+ "slug": [
+ "build",
+ "add-search"
+ ],
+ "urlPath": "/docs/build/add-search",
+ "title": "Add search",
+ "description": "Generate a static docs search index, query it at runtime, and optionally stream source-grounded answers.",
+ "relativePath": "build/add-search",
+ "extension": ".mdx",
+ "groups": [
+ "docs-site"
+ ],
+ "globKey": "../../../../../docs/build/add-search.mdx"
+ },
+ {
+ "slug": [
+ "build",
+ "build-a-docs-site"
+ ],
+ "urlPath": "/docs/build/build-a-docs-site",
+ "title": "Build a docs site",
+ "description": "Pick the right leadtype integration shape for your docs app, and what each path gives you.",
+ "relativePath": "build/build-a-docs-site",
+ "extension": ".mdx",
+ "groups": [
+ "docs-site"
+ ],
+ "globKey": "../../../../../docs/build/build-a-docs-site.mdx"
+ },
+ {
+ "slug": [
+ "build",
+ "generate-static-artifacts"
+ ],
+ "urlPath": "/docs/build/generate-static-artifacts",
+ "title": "Generate static artifacts",
+ "description": "Run leadtype generate from your build pipeline to write llms.txt, markdown mirrors, search index, sitemap, and agent-readability files to disk.",
+ "relativePath": "build/generate-static-artifacts",
+ "extension": ".mdx",
+ "groups": [
+ "docs-site"
+ ],
+ "globKey": "../../../../../docs/build/generate-static-artifacts.mdx"
+ },
+ {
+ "slug": [
+ "build",
+ "integrate-with-fumadocs"
+ ],
+ "urlPath": "/docs/build/integrate-with-fumadocs",
+ "title": "Integrate with Fumadocs",
+ "description": "Wire leadtype's content layer into a fumadocs app for nav, search, and includes.",
+ "relativePath": "build/integrate-with-fumadocs",
+ "extension": ".mdx",
+ "groups": [
+ "docs-site"
+ ],
+ "globKey": "../../../../../docs/build/integrate-with-fumadocs.mdx"
+ },
+ {
+ "slug": [
+ "build",
+ "optimize-docs-for-agents"
+ ],
+ "urlPath": "/docs/build/optimize-docs-for-agents",
+ "title": "Optimize docs for agents",
+ "description": "Set up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.",
+ "relativePath": "build/optimize-docs-for-agents",
+ "extension": ".mdx",
+ "groups": [
+ "docs-site"
+ ],
+ "globKey": "../../../../../docs/build/optimize-docs-for-agents.mdx"
+ },
+ {
+ "slug": [
+ "build",
+ "use-the-source-primitive"
+ ],
+ "urlPath": "/docs/build/use-the-source-primitive",
+ "title": "Use the source primitive",
+ "description": "Wire createDocsSource into Next, Astro, Vite, Nuxt, SvelteKit, or any MDX-aware bundler. Same primitive, multiple host shapes.",
+ "relativePath": "build/use-the-source-primitive",
+ "extension": ".mdx",
+ "groups": [
+ "docs-site"
+ ],
+ "globKey": "../../../../../docs/build/use-the-source-primitive.mdx"
+ },
+ {
+ "slug": [
+ "build",
+ "validate-in-ci"
+ ],
+ "urlPath": "/docs/build/validate-in-ci",
+ "title": "Validate in CI",
+ "description": "Run leadtype lint in CI so frontmatter, navigation, and link issues fail PRs before publish.",
+ "relativePath": "build/validate-in-ci",
+ "extension": ".mdx",
+ "groups": [
+ "docs-site"
+ ],
+ "globKey": "../../../../../docs/build/validate-in-ci.mdx"
+ },
+ {
+ "slug": [
+ "how-it-works"
+ ],
+ "urlPath": "/docs/how-it-works",
+ "title": "How it works",
+ "description": "The mental model: one MDX source, a remark pipeline, two output modes, three audiences.",
+ "relativePath": "how-it-works",
+ "extension": ".mdx",
+ "groups": [
+ "get-started"
+ ],
+ "globKey": "../../../../../docs/how-it-works.mdx"
+ },
+ {
+ "slug": [],
+ "urlPath": "/docs",
+ "title": "Leadtype",
+ "description": "One MDX source. Hosted docs artifacts, package-bundled AGENTS.md, and search output from the same pipeline.",
+ "relativePath": "index",
+ "extension": ".mdx",
+ "groups": [
+ "get-started"
+ ],
+ "globKey": "../../../../../docs/index.mdx"
+ },
+ {
+ "slug": [
+ "methodology"
+ ],
+ "urlPath": "/docs/methodology",
+ "title": "Methodology",
+ "description": "How leadtype differs from Fumadocs, Starlight, and Mintlify.",
+ "relativePath": "methodology",
+ "extension": ".mdx",
+ "groups": [
+ "get-started"
+ ],
+ "globKey": "../../../../../docs/methodology.mdx"
+ },
+ {
+ "slug": [
+ "package-docs",
+ "bundle"
+ ],
+ "urlPath": "/docs/package-docs/bundle",
+ "title": "Bundle docs into a package",
+ "description": "Ship agent-readable docs inside an npm tarball — AGENTS.md at the package root plus per-topic .md files.",
+ "relativePath": "package-docs/bundle",
+ "extension": ".mdx",
+ "groups": [
+ "package-docs"
+ ],
+ "globKey": "../../../../../docs/package-docs/bundle.mdx"
+ },
+ {
+ "slug": [
+ "quickstart"
+ ],
+ "urlPath": "/docs/quickstart",
+ "title": "Quickstart",
+ "description": "Install leadtype, author your first MDX page, and create a source. Then plug it into whatever framework you're using.",
+ "relativePath": "quickstart",
+ "extension": ".mdx",
+ "groups": [
+ "get-started"
+ ],
+ "globKey": "../../../../../docs/quickstart.mdx"
+ },
+ {
+ "slug": [
+ "reference",
+ "cli"
+ ],
+ "urlPath": "/docs/reference/cli",
+ "title": "CLI",
+ "description": "leadtype generate and leadtype lint — flags, exit codes, and JSON output.",
+ "relativePath": "reference/cli",
+ "extension": ".mdx",
+ "groups": [
+ "reference"
+ ],
+ "globKey": "../../../../../docs/reference/cli.mdx"
+ },
+ {
+ "slug": [
+ "reference",
+ "convert"
+ ],
+ "urlPath": "/docs/reference/convert",
+ "title": "Convert",
+ "description": "MDX-to-markdown conversion APIs from leadtype/convert.",
+ "relativePath": "reference/convert",
+ "extension": ".mdx",
+ "groups": [
+ "reference"
+ ],
+ "globKey": "../../../../../docs/reference/convert.mdx"
+ },
+ {
+ "slug": [
+ "reference",
+ "evals"
+ ],
+ "urlPath": "/docs/reference/evals",
+ "title": "Evals",
+ "description": "How Leadtype benchmarks AGENTS.md, llms.txt, and llms-full.txt output before changing defaults.",
+ "relativePath": "reference/evals",
+ "extension": ".mdx",
+ "groups": [
+ "reference"
+ ],
+ "globKey": "../../../../../docs/reference/evals.mdx"
+ },
+ {
+ "slug": [
+ "reference",
+ "lint"
+ ],
+ "urlPath": "/docs/reference/lint",
+ "title": "Lint rules",
+ "description": "Schema, link, and navigation checks. CLI and library API.",
+ "relativePath": "reference/lint",
+ "extension": ".mdx",
+ "groups": [
+ "reference"
+ ],
+ "globKey": "../../../../../docs/reference/lint.mdx"
+ },
+ {
+ "slug": [
+ "reference",
+ "llm"
+ ],
+ "urlPath": "/docs/reference/llm",
+ "title": "LLM files",
+ "description": "Generate llms.txt for hosted websites and AGENTS.md for npm-bundled offline reading.",
+ "relativePath": "reference/llm",
+ "extension": ".mdx",
+ "groups": [
+ "reference"
+ ],
+ "globKey": "../../../../../docs/reference/llm.mdx"
+ },
+ {
+ "slug": [
+ "reference",
+ "mdx"
+ ],
+ "urlPath": "/docs/reference/mdx",
+ "title": "leadtype/mdx",
+ "description": "Tag type contracts and the build-time source preset for consumers rendering MDX themselves.",
+ "relativePath": "reference/mdx",
+ "extension": ".mdx",
+ "groups": [
+ "reference"
+ ],
+ "globKey": "../../../../../docs/reference/mdx.mdx"
+ },
+ {
+ "slug": [
+ "reference",
+ "remark"
+ ],
+ "urlPath": "/docs/reference/remark",
+ "title": "Remark plugins",
+ "description": "The default plugin stack that flattens MDX components into markdown.",
+ "relativePath": "reference/remark",
+ "extension": ".mdx",
+ "groups": [
+ "reference"
+ ],
+ "globKey": "../../../../../docs/reference/remark.mdx"
+ },
+ {
+ "slug": [
+ "reference",
+ "search"
+ ],
+ "urlPath": "/docs/reference/search",
+ "title": "Search",
+ "description": "Static search index, runtime helpers, and source-grounded answer streaming.",
+ "relativePath": "reference/search",
+ "extension": ".mdx",
+ "groups": [
+ "reference"
+ ],
+ "globKey": "../../../../../docs/reference/search.mdx"
+ },
+ {
+ "slug": [
+ "reference",
+ "source"
+ ],
+ "urlPath": "/docs/reference/source",
+ "title": "createDocsSource",
+ "description": "Framework-neutral docs source primitive — navigation, page loader, search index, and include resolver.",
+ "relativePath": "reference/source",
+ "extension": ".mdx",
+ "groups": [
+ "reference"
+ ],
+ "globKey": "../../../../../docs/reference/source.mdx"
+ }
+]
diff --git a/apps/example/src/generated/docs-search-content.json b/apps/example/src/generated/docs-search-content.json
index 75d5ec8..62dafa6 100644
--- a/apps/example/src/generated/docs-search-content.json
+++ b/apps/example/src/generated/docs-search-content.json
@@ -1 +1 @@
-{"version":2,"generatedAt":"2026-05-11T23:20:44.313Z","chunks":["Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nLeadtype does not ship UI components. Your docs app owns runtime rendering, styling, and accessibility — it only has to honor a small naming contract so the remark pipeline can flatten each component into markdown for agents, search, and llms-full.txt .","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nWhy flatten at all?\n\nInteractive MDX components like Body content goes here. ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nCards\n\nA grid of short, linked entry points. Flattens to a bullet list of links. Convert Remark Search\n\n```tsx ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nSteps\n\nNumbered walkthroughs. Flattens to an ordered list with bold step titles. 1. Author docs in MDX Use the components in this list as authoring affordances. 2. Run the conversion leadtype generate writes flattened markdown to public/docs/ . 3. Serve both formats HTML for humans, .md for agents — same URL, content negotiated by the Accept header.\n\n```tsx Use the components in this list.`leadtype generate` writes flattened markdown. ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nTabs\n\nGroup equivalent content. Flattens to bold headings followed by content so agents do not need a JSX-aware renderer to read every variant. tanstack-start Use a Vite middleware dev/preview and a Nitro middleware prod to negotiate the Accept header. next-js Wire content negotiation in middleware.ts and serve .md from a route handler. vite A configureServer middleware is enough for static deployments where .md files live in public/ .\n\n```tsx ……… ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nCommandTabs\n\nPackage-manager-aware install or run commands. Flattens to a markdown table with one row per manager. Use mode=\"install\" when command is a package name, mode=\"run\" when command is a CLI name, and mode=\"create\" for starter commands. Use the commands prop for exact per-manager overrides. Package manager Command -- -- npm npm install leadtype pnpm pnpm add leadtype yarn yarn add leadtype bun bun add leadtype Package manager Command -- -- npm npx leadtype lint pnpm pnpm dlx leadtype lint yarn yarn dlx leadtype lint bun bunx leadtype lint\n\n```tsx ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nPrompt\n\nDisplays an agent-ready prompt with a copy action. Flattening preserves the prompt body as a fenced prompt block so copied instructions also survive in .md , root llms-full.txt , and bundled AGENTS.md output. Copy prompt for your coding agent Use this after generating artifacts.\n\n```tsx Inspect `public/docs/agent-readability.json`, then wire markdown responses before the HTML docs route. ``` ```prompt Inspect `public/docs/agent-readability.json`, then wire markdown responses before the HTML docs route. ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nAudience\n\nSplits browser-only and agent-only guidance without forking the page. Human content renders in the docs UI and is omitted from markdown output; agent content is hidden in the browser and included in generated markdown. This sentence appears only in generated markdown for agents.\n\n```tsx Click the robot icon in the header.Read generated markdown before editing runtime routes. ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nFileTree\n\nShows project structure in guides and release instructions. Flattening emits a fenced text tree so agents can read the same hierarchy without JSX.\n\n```tsx ``` ```text public/ ├── llms.txt └── docs/ └── index.md ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nAccordion\n\nCollapsible details for secondary content. Flattening ignores open/closed state and emits every item — accordions are not a place to hide content from agents. When should I use accordions? Use them for supporting details, troubleshooting notes, and optional reference material. Closed content is still flattened by the remark pipeline. Are accordions a good place to hide content from LLMs? No. Conversion ignores the open/closed state and emits everything inside.\n\n```tsx Use them for supporting details and optional reference material. ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nTopicSwitcher\n\nNavigation across equivalent docs topics — frameworks, SDKs, runtimes, deployment targets, product areas. Reader-facing only; it does not automatically read LLM topic config. Framework React — React integration Vue — Vue integration Svelte — Svelte integration\n\n```tsx ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nTypeTable and ExtractedTypeTable\n\nTypeTable is for explicit prop or type rows you already know. ExtractedTypeTable reads a TypeScript file at conversion time and extracts the table from a named type — keep its path stable. Property Type Description Default Required -- -- -- -- -- title string Heading rendered above the callout body. - ✅ Required variant CalloutVariant Visual treatment for the callout. info Optional deprecated \\ \\ boolean\\ \\ deprecated Marks the row as deprecated. false Optional\n\n```tsx ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nExample\n\nData-driven preview and source examples. The host component receives code as data; add file loaders or dynamic imports outside leadtype when an example needs app-specific behavior.\n\n```tsx The host app owns styling and runtime components while leadtype owns conversion. ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nMermaid\n\nDiagrams authored as plain text. Renders client-side as interactive SVG. Flattening preserves the source as a fenced mermaid block so other tools can render the diagram from the markdown copy.\n\n```tsx |remark| Markdown Markdown -->|llms.txt| Agents`} /> ``` ```mermaid `graph LR MDX -->|remark| Markdown Markdown -->|search index| API Markdown -->|llms.txt| Agents` ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nGuidelines\n\nKeep runtime components in your docs app. Leadtype stays out of UI. Keep component names stable. Renaming resolver page1 --> resolver page2 --> resolver page3 --> resolver resolver --> nav resolver --> llms resolver --> agents` ```","Frontmatter\n\nRequired fields, group semantics, and how authored MDX becomes a navigation tree.\n\nFrontmatter\n\nHow groups become a nav tree\n\nNested groups\n\nDeclare children in the config to build deeper trees A page sets group remote-source and lands in that nested slot. Only leaf groups no children directly contain pages; non-leaf groups are headings only.\n\n```ts { slug: \"docs-site\", title: \"Build a Docs Site\", children: [ { slug: \"remote-source\", title: \"Remote source\" }, { slug: \"connect-docs-site\", title: \"Connect a docs site\" }, ], } ```","Frontmatter\n\nRequired fields, group semantics, and how authored MDX becomes a navigation tree.\n\nFrontmatter\n\nOptional fields\n\nThe default lint schema also accepts Property Type Description Default Required -- -- -- -- -- icon string Icon name resolved by your sidebar component. - Optional deprecated boolean Marks the page as deprecated in nav and search. - Optional deprecatedReason string Short message paired with deprecated. - Optional experimental boolean Marks the page as experimental. - Optional canary boolean Hides from stable channels. - Optional new boolean Highlights the page as recently added. - Optional draft boolean Excludes from generation entirely. - Optional tags string\\ Free-form tags for search facets. - Optional availableIn Array\\<\\ framework, url?, title? Cross-framework availability map for TopicSwitcher pages. - Optional full boolean Layout hint for docs UIs that support full-width pages. - Optional lastModified and lastAuthor are filled in automatically when you pass --enrich-git to the CLI. Don't author them by hand.","Frontmatter\n\nRequired fields, group semantics, and how authored MDX becomes a navigation tree.\n\nFrontmatter\n\nLint rules\n\nleadtype lint enforces the schema, so violations surface in CI before they reach a build. The relevant rules schema — a required field is missing or has the wrong type. unknown-field — a top-level field isn't in the schema warn by default; --error-unknown to fail . parse-error — frontmatter or meta.json doesn't parse. invalid-link — a /docs/... link points to a route that doesn't exist. unresolved-placeholder — a doc URL still contains an unresolved framework placeholder. cross-framework-link — a framework-scoped page links to another framework's docs. See Lint rules for the full reference and how to extend the schema.","Frontmatter\n\nRequired fields, group semantics, and how authored MDX becomes a navigation tree.\n\nFrontmatter\n\nWhat this gives you\n\nOnce frontmatter is consistent, the rest of the pipeline works without per-page configuration. The same group value drives The sidebar position The llms.txt section Search metadata and AGENTS.md grouping The search filtering UI if you build one Cross-framework link checks in lint One field, one source of truth.","Add search\n\nGenerate a static docs search index, query it at runtime, and optionally stream source-grounded answers.\n\nAdd search\n\nLeadtype search is static by default. Build time produces two JSON files; runtime code imports or fetches those files and queries them without a database.","Add search\n\nGenerate a static docs search index, query it at runtime, and optionally stream source-grounded answers.\n\nAdd search\n\nGenerate the files\n\nleadtype generate writes search files in site mode If you run the pipeline from scripts, call the search generator after conversion This writes The index contains compact ranking data. The content store contains the text used for excerpts and answer context.\n\n```bash npx leadtype generate --src . --out public --base-url https://example.com ``` ```ts import { generateDocsSearchFiles } from \"leadtype/search/node\"; await generateDocsSearchFiles({ outDir: \"public\", baseUrl: \"https://example.com\", }); ``` ```txt public/docs/search-index.json public/docs/search-content.json ```","Add search\n\nGenerate a static docs search index, query it at runtime, and optionally stream source-grounded answers.\n\nAdd search\n\nQuery at runtime\n\nResults include page URLs, heading paths, hash URLs, and snippets. Render them in your own search UI.\n\n```ts import { searchDocs, type DocsSearchContentStore, type DocsSearchIndex, } from \"leadtype/search\"; import contentJson from \"../public/docs/search-content.json\"; import indexJson from \"../public/docs/search-index.json\"; const index = indexJson as DocsSearchIndex; const content = contentJson as DocsSearchContentStore; const results = searchDocs(index, \"run lint\", { content }); ```","Add search\n\nGenerate a static docs search index, query it at runtime, and optionally stream source-grounded answers.\n\nAdd search\n\nAdd vocabulary aliases\n\nSearch starts with lexical matching, stemming, prefix matches, typo-tolerant fallbacks, and a small built-in synonym map. Add product-specific synonyms only when users search with words your docs do not use\n\n```ts const results = searchDocs(index, \"starter\", { content, synonyms: { starter: [\"quickstart\", \"getting started\"], }, }); ```","Add search\n\nGenerate a static docs search index, query it at runtime, and optionally stream source-grounded answers.\n\nAdd search\n\nOptional AI answers\n\nUse source-grounded answers only after basic search works. Leadtype retrieves chunks from the static index, builds a constrained prompt, and leaves model choice to the provider entry point you import Display sources next to the streamed response. Do not ask the model to answer from memory; the answer context is built from retrieved docs chunks.\n\n```ts import { streamDocsAnswer } from \"leadtype/search/vercel\"; const { response, sources } = streamDocsAnswer({ index, content, query: \"How do I run docs lint in CI?\", model: \"openai/gpt-5.5\", productName: \"My Library\", }); ```","Add search\n\nGenerate a static docs search index, query it at runtime, and optionally stream source-grounded answers.\n\nAdd search\n\nGuard the endpoint\n\nFor API routes that accept user queries, use the request helpers from leadtype/search validateDocsQuery to trim and cap query text. readJsonWithLimit to reject oversized JSON bodies. getClientIdentifier to read common proxy IP headers. createMemoryRateLimiter for demos. Production apps should adapt the rate limiter interface to a shared store such as Redis, Vercel KV, Cloudflare KV, or Durable Objects.","Add search\n\nGenerate a static docs search index, query it at runtime, and optionally stream source-grounded answers.\n\nAdd search\n\nVerify\n\npublic/docs/search-index.json and public/docs/search-content.json exist and are non-empty. Searching for an exact API name returns the expected reference page. Searching for a guide phrase returns a result with a section hash. AI answers cite sources from the returned sources metadata.","Connect a docs site\n\nBuild a shared docs app from source docs that live with the code they document.\n\nConnect a docs site\n\nUse this path when you run a docs app that renders docs from one or more source repos. This is the main Leadtype docs-site model content stays next to the code it documents, while the docs app clones or checks out that content during build and serves the generated artifacts. Your framework still owns routes, HTML, styling, and deployment. Leadtype owns the source-to-artifact pipeline.","Connect a docs site\n\nBuild a shared docs app from source docs that live with the code they document.\n\nConnect a docs site\n\nThe flow\n\n```mermaid `flowchart LR repo[\"source repo / docs/*.mdx\"] clone[\"checkout or clone / .docs-src/c15t\"] lint[\"leadtype lint\"] generate[\"leadtype generate\"] public[\"public/ / llms.txt · llms-full.txt / docs/*.md / search · agent metadata\"] app[\"docs app / routing + HTML\"] repo --> clone --> lint --> generate --> public --> app` ```","Connect a docs site\n\nBuild a shared docs app from source docs that live with the code they document.\n\nConnect a docs site\n\nFetch the source repo\n\nIn CI, check out the docs source before the docs app build. For a public repo, a shallow clone is enough For private repos, use your CI platform's checkout action or a read-only deploy key. The important part is that Leadtype receives a normal filesystem path whose root contains docs/ .\n\n```bash rm -rf .docs-src/c15t git clone --depth 1 https://github.com/c15t/c15t .docs-src/c15t ```","Connect a docs site\n\nBuild a shared docs app from source docs that live with the code they document.\n\nConnect a docs site\n\nLint before generate\n\nRun lint against the fetched docs before writing generated output Lint fails with file and line context for frontmatter, internal links, placeholders, and schema issues. That is easier to debug than a later app build using stale or partial artifacts.\n\n```bash npx leadtype lint .docs-src/c15t/docs \\ --format github \\ --error-unknown \\ --max-warnings 0 ```","Connect a docs site\n\nBuild a shared docs app from source docs that live with the code they document.\n\nConnect a docs site\n\nGenerate hosted artifacts\n\nPoint --src at the fetched repository root and --out at the docs app public directory That command writes public/llms.txt and public/llms-full.txt public/docs/ .md public/docs/search-index.json and public/docs/search-content.json public/docs/sitemap.xml , sitemap.md , robots.txt , and agent-readability.json Use --json in CI so automation can record resolved groups, output files, filters, and search index stats.\n\n```bash npx leadtype generate \\ --src .docs-src/c15t \\ --out public \\ --base-url https://docs.example.com \\ --json ```","Connect a docs site\n\nBuild a shared docs app from source docs that live with the code they document.\n\nConnect a docs site\n\nWire it into the app build\n\nMake the source checkout, lint, and generation steps run before the framework build If the docs source and docs app live in the same repo, skip docs fetch and point --src at .\n\n```json { \"scripts\": { \"docs:fetch\": \"rm -rf .docs-src/c15t && git clone --depth 1 https://github.com/c15t/c15t .docs-src/c15t\", \"docs:lint\": \"leadtype lint .docs-src/c15t/docs --format github --error-unknown --max-warnings 0\", \"docs:generate\": \"leadtype generate --src .docs-src/c15t --out public --base-url https://docs.example.com --json\", \"build\": \"npm run docs:fetch && npm run docs:lint && npm run docs:generate && vite build\" } } ``` ```bash npx leadtype lint docs --error-unknown npx leadtype generate --src . --out public --base-url https://docs.example.com ```","Connect a docs site\n\nBuild a shared docs app from source docs that live with the code they document.\n\nConnect a docs site\n\nConfigure product and groups\n\nThe source repo should own docs/docs.config.ts so its groups and product metadata version with the docs. leadtype generate loads this file automatically from the docs folder Pages declare group in frontmatter. The config declares titles, order, and descriptions. Together they drive navigation, llms.txt , search metadata, and package AGENTS.md sections. If no config exists, the CLI infers groups from frontmatter, but inferred groups have no descriptions or custom order. See Frontmatter.\n\n```ts import { defineDocsConfig } from \"leadtype\"; export default defineDocsConfig({ product: { name: \"c15t\", summary: \"Consent infrastructure for modern web apps.\", bullets: [\"Framework integrations.\", \"Consent primitives.\", \"Audit-friendly docs.\"], bestStartingPoints: [{ urlPath: \"/docs\" }, { urlPath: \"/docs/quickstart\" }], }, groups: [ { slug: \"get-started\", title: \"Get Started\" }, { slug: \"guides\", title: \"Guides\" }, { slug: \"reference\", title: \"Reference\" }, ], }); ```","Connect a docs site\n\nBuild a shared docs app from source docs that live with the code they document.\n\nConnect a docs site\n\nUse scripts for custom pipelines\n\nThe CLI is the happy path. Use the library APIs directly when you need custom plugin order, filters, or generated JSON paths. Keep conversion first because LLM files, search, and Agent Readability artifacts read the generated markdown. Write navigation to a generated JSON file if your sidebar should use the same group tree as llms.txt . Write agentReadability.manifest if your runtime needs to merge docs pages with marketing, blog, changelog, or product routes.\n\n```ts import { convertAllMdx } from \"leadtype/convert\"; import { generateAgentReadabilityArtifacts, generateLLMFullContextFiles, generateLlmsTxt, resolveDocsNavigation, } from \"leadtype/llm\"; import { defaultRemarkPlugins, remarkInclude } from \"leadtype/remark\"; import { generateDocsSearchFiles } from \"leadtype/search/node\"; import docsConfig from \"../.docs-src/c15t/docs/docs.config\"; const sourceRoot = \".docs-src/c15t\"; await convertAllMdx({ srcDir: `${sourceRoot}/docs`, outDir: \"public/docs\", remarkPlugins: [remarkInclude, ...defaultRemarkPlugins], enrichFrontmatterFromGit: true, }); await generateLlmsTxt({ srcDir: sourceRoot, outDir: \"public\", baseUrl: \"https://docs.example.com\", product: docsConfig.product, groups: docsConfig.groups, }); await generateLLMFullContextFiles({ outDir: \"public\", baseUrl: \"https://docs.example.com\", product: { name: docsConfig.product.name }, groups: docsConfig.groups, }); await generateDocsSearchFiles({ outDir: \"public\", baseUrl: \"https://docs.example.com\", }); const agentReadability = await generateAgentReadabilityArtifacts({ outDir: \"public\", baseUrl: \"https://docs.example.com\", product: docsConfig.product, groups: docsConfig.groups, }); const","Connect a docs site\n\nBuild a shared docs app from source docs that live with the code they document.\n\nConnect a docs site\n\nUse scripts for custom pipelines\n\nait generateAgentReadabilityArtifacts({ outDir: \"public\", baseUrl: \"https://docs.example.com\", product: docsConfig.product, groups: docsConfig.groups, }); const navigation = await resolveDocsNavigation({ srcDir: sourceRoot, baseUrl: \"https://docs.example.com\", groups: docsConfig.groups, }); ```","Connect a docs site\n\nBuild a shared docs app from source docs that live with the code they document.\n\nConnect a docs site\n\nWire the app runtime\n\nAfter generation, choose the runtime pieces your site needs Render source MDX as HTML with your own components Render MDX and TOC. Return markdown for agent requests and serve discovery files Optimize docs for agents. Add local search and optional source-grounded answers Add search.","Connect a docs site\n\nBuild a shared docs app from source docs that live with the code they document.\n\nConnect a docs site\n\nVerify\n\nAfter a clean build, inspect these files public/docs/index.md — converted markdown for the source repo home page. public/llms.txt — hosted routing index with page-level markdown links. public/llms-full.txt — all generated markdown docs in one fallback file. public/docs/search-index.json and public/docs/search-content.json — non-empty search files. public/docs/agent-readability.json — manifest for markdown responses, JSON-LD, sitemap, and robots helpers. Then start your app and check at least one browser HTML page and one markdown response path.","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\nUse this guide when you already have a docs site and want agents to find, fetch, attribute, and cite the same content humans read in the browser. Leadtype handles the generated files. Your app wires those files into routing and HTML. The default output shape is based on the repo's agent evals. See Evals for the benchmark summary and the open question around larger-corpus llms-full.txt scaling.","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\nWhat good looks like\n\nAn agent-readable docs site has four layers 1. Discovery files /llms.txt , /sitemap.xml , /sitemap.md , and /robots.txt tell agents what exists and where to start. 2. Markdown retrieval Each docs page has a markdown mirror at /docs/page.md , and agent requests to /docs/page can receive markdown instead of HTML. 3. Structured HTML metadata Human HTML pages include JSON-LD, canonical links, and markdown alternate links so agents can extract page identity without guessing from the DOM. 4. Attribution metadata Markdown responses include canonical url and last updated frontmatter so copied content keeps its source and freshness.","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\n1. Generate the artifacts\n\nRun the site-mode pipeline before your app build This writes the docs-scoped files under public/docs/ and the top-level public/llms.txt The generated agent-readability.json manifest is the bridge between build-time content and runtime requests. It contains page URLs, markdown mirror paths, titles, descriptions, group navigation, and freshness dates.\n\n```bash npx leadtype generate \\ --src . \\ --out public \\ --base-url https://leadtype.dev \\ --name \"My product\" \\ --summary \"One sentence about the product.\" ``` ```txt public/ ├── llms.txt ├── llms-full.txt └── docs/ ├── index.md ├── quickstart.md ├── llms.txt ├── sitemap.xml ├── sitemap.md ├── robots.txt └── agent-readability.json ```","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\n2. Add one middleware\n\nPut the agent-readable routes before your HTML docs route. This Node/Bun example handles root discovery files, docs-scoped discovery files, direct .md URLs, and Accept text/markdown requests in one place If you also have marketing, blog, changelog, or product pages, pass them through the optional pages field — the regenerator merges them into the rebased output The other generated artifacts — /llms.txt , /docs/llms.txt , /llms-full.txt , /docs/agent-readability.json — use root-relative links and serve fine as static files straight from public/ . Keep the docs-scoped versions too /docs/sitemap.xml etc. . Audits and agents may request both /sitemap.xml and /docs/sitemap.xml , especially when the audited URL is /docs .\n\n```ts import { readFile } from \"node:fs/promises\"; import { join } from \"node:path\"; import manifestJson from \"../public/docs/agent-readability.json\" with { type: \"json\", }; import { createAgentMarkdownResponse, createRobotsTxtResponse, createSitemapMarkdownResponse, createSitemapXmlResponse, type AgentReadabilityManifest, type MarkdownMirrorTarget, } from \"leadtype/llm/readability\"; const manifest = { ...manifestJson, version: 1, } as AgentReadabilityManifest; async function readMarkdownFile( target: MarkdownMirrorTarget ): Promise { try { return await readFile(join(process.cwd(), \"public\", target.filePath), \"utf8\"); } catch (error) { if ( typeof error === \"object\" && error !== null && \"code\" in error && (error.code === \"ENOENT\" || error.code === \"ENOTDIR\") ) { return null; } throw error; } } export async function handleDocsRequest( request: Request ): Promise { if (request.method !== \"GET\" && request.method !== \"HEAD\") { return null; } const url = new URL(request.url); const requestOrigin = url.origin; switch (url.pathname) { case \"/sitemap.xml\": case \"/docs/sitemap.xml\": return createSitemapXmlResponse({ manifest, requestOrigin }); case","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\n2. Add one middleware\n\nstOrigin = url.origin; switch (url.pathname) { case \"/sitemap.xml\": case \"/docs/sitemap.xml\": return createSitemapXmlResponse({ manifest, requestOrigin }); case \"/sitemap.md\": case \"/docs/sitemap.md\": return createSitemapMarkdownResponse({ manifest, requestOrigin }); case \"/robots.txt\": return createRobotsTxtResponse({ manifest, requestOrigin }); case \"/docs/robots.txt\": return createRobotsTxtResponse({ manifest, requestOrigin, sitemapUrlPath: \"/docs/sitemap.xml\", }); default: return createAgentMarkdownResponse({ urlPath: url.pathname, method: request.method, headers: Object.fromEntries(request.headers), manifest, readMarkdownFile, requestOrigin, }); } } ``` ```ts return createSitemapXmlResponse({ manifest, requestOrigin, pages: [...manifest.pages, ...marketingPages, ...blogPages], }); ```","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\n3. Add JSON-LD to docs pages\n\nUse the manifest entry for the current page and render Schema.org JSON-LD into the HTML head Use renderJsonLd page, manifest if your framework has a typed metadata API. Use renderJsonLdScript page, manifest if your framework expects an HTML string. Also add canonical and markdown alternate links The JSON-LD gives agents the page title, description, canonical URL, last modified date, and breadcrumbs without scraping your rendered layout.\n\n```ts import agentManifest from \"../public/docs/agent-readability.json\"; import { renderJsonLd, renderJsonLdScript } from \"leadtype/llm/readability\"; const page = agentManifest.pages.find( (entry) => entry.urlPath === \"/docs/quickstart\" ); if (page) { const jsonLd = renderJsonLd(page, agentManifest); const script = renderJsonLdScript(page, agentManifest); } ``` ```html ```","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\n4. Return markdown to agents\n\nThe middleware above uses createAgentMarkdownResponse . It returns a Web Response or null when the path is not an agent-oriented markdown request and handles Accept text/markdown and Accept text/plain content negotiation q-values respected . Known AI user-agent headers GPTBot, ClaudeBot, Bingbot, AmazonBot, MetaExternalAgent, PerplexityBot, MistralBot, AppleBot, ByteSpider, YouBot, … . Direct .md URLs such as /docs/quickstart.md . canonical url and last updated frontmatter aliases injected automatically. 200 markdown responses for missing docs pages, so agents do not discard the body. Content-Type text/markdown; charset=utf-8 , Vary Accept , User-Agent , Link <… ; rel=\"canonical\" , Cache-Control public, max-age=300, must-revalidate . readMarkdownFile may be sync or async. In Node/Bun, read from disk. In Cloudflare, fetch from KV/R2 or an asset binding. In Vercel Edge, fetch from the deployment's static asset URL. Put that logic wherever your framework can intercept docs requests before its HTML route Framework/runtime Where it usually goes -- -- TanStack Start / nitro server/middleware/agent-readability.ts h3 .","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\n4. Return markdown to agents\n\nn intercept docs requests before its HTML route Framework/runtime Where it usually goes -- -- TanStack Start / nitro server/middleware/agent-readability.ts h3 . One middleware handles both the markdown response and the sitemap/robots regenerators — runs in dev, preview, and prod. See apps/example/server/middleware/agent-readability.ts for the canonical reference. Nuxt server/middleware/agent-readability.ts h3 — same shape as the TanStack Start example. Next.js middleware.ts Edge or a catch-all route handler before the docs page. Astro An endpoint at pages/docs/ ...slug .md.ts or astro middleware . Cloudflare Workers/Pages Worker fetch handler with KV/R2 asset binding for the markdown reader. Express/Hono/Fastify Middleware before the docs HTML route. Tip if you keep static sitemap.xml / sitemap.md / robots.txt files in your build output, your framework's static handler may serve them before your middleware can rebase URLs to the live origin. Either delete the static copies after the build so the middleware always runs or make sure your middleware is registered ahead of static-asset serving.","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\n4. Return markdown to agents\n\norigin. Either delete the static copies after the build so the middleware always runs or make sure your middleware is registered ahead of static-asset serving. Do not rewrite llms.txt , sitemap.xml , sitemap.md , robots.txt , llms-full.txt , or agent-readability.json to page markdown. The helper leaves those artifact paths alone.","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\n4. Return markdown to agents\n\nWhy the sitemap and robots responses are regenerated, not static\n\nsitemap.xml 's ; function textFromChildren(children: unknown): string { if (typeof children === \"string\" || typeof children === \"number\") { return String(children); } if (Array.isArray(children)) { return children.map(textFromChildren).join(\"\"); } if (isValidElement(children)) { const elementProps = children.props as { children?: unknown }; return textFromChildren(elementProps.children); } return \"\"; } function createHeading(level: 1 | 2 | 3 | 4 | 5 | 6) { return ({ children, id, ...props }: HeadingProps) => { const Component = `h${level}` as const; const headingId = id ?? slugifyDocsHeading(textFromChildren(children)); return ( {children} ); }; } ```","Render MDX and TOC\n\nSet up runtime MDX components, stable heading IDs, and a table of contents from the generated navigation manifest.\n\nRender MDX and TOC\n\nGenerate navigation with TOC data\n\nresolveDocsNavigation includes toc on every page. The default range is h2 to h3 . Write the navigation object to a generated JSON file and import it from your sidebar.\n\n```ts import { resolveDocsNavigation } from \"leadtype/llm\"; import docsConfig from \"../docs/docs.config\"; const navigation = await resolveDocsNavigation({ srcDir: \".\", baseUrl: \"https://example.com\", groups: docsConfig.groups, toc: { minLevel: 2, maxLevel: 4 }, }); ```","Render MDX and TOC\n\nSet up runtime MDX components, stable heading IDs, and a table of contents from the generated navigation manifest.\n\nRender MDX and TOC\n\nRender the sidebar\n\nLook up the current page in the manifest and pass currentPage.toc to your sidebar component. The example app includes a complete React implementation with scroll-spy, hash sync, active highlighting, and sticky positioning apps/example/src/components/table-of-contents.tsx","Render MDX and TOC\n\nSet up runtime MDX components, stable heading IDs, and a table of contents from the generated navigation manifest.\n\nRender MDX and TOC\n\nTroubleshooting\n\nTOC links do not scroll anywhere. Your heading IDs do not match the extracted slugs. Use slugifyDocsHeading in the rendered heading components. A page TOC is empty. All headings are outside the configured minLevel and maxLevel range. Defaults exclude h1 and headings deeper than h3 . Sidebar order differs from llms.txt. The app is not using the same docs.config.ts groups as the generation step.","Validate in CI\n\nRun leadtype lint in CI so frontmatter, navigation, and link issues fail PRs before publish.\n\nValidate in CI\n\nleadtype lint reads source MDX, runs the schema and link checks, and exits non-zero on errors. Wire it into CI so docs PRs fail fast on the same rules that would otherwise blow up leadtype generate later in the pipeline.","Validate in CI\n\nRun leadtype lint in CI so frontmatter, navigation, and link issues fail PRs before publish.\n\nValidate in CI\n\nWhat it catches\n\nMissing or wrong-typed frontmatter fields schema rule . Top-level frontmatter fields not in the schema unknown-field . Frontmatter or meta.json that doesn't parse parse-error . Internal /docs/... links pointing at routes that don't exist invalid-link . Unresolved framework placeholders left in URLs unresolved-placeholder . Cross-framework links from a framework-scoped page to a different framework's docs cross-framework-link . See Lint reference for the full rule list and how to extend the schema.","Validate in CI\n\nRun leadtype lint in CI so frontmatter, navigation, and link issues fail PRs before publish.\n\nValidate in CI\n\nGitHub Actions\n\nUse --format github so violations render as inline annotations on the PR --error-unknown upgrades unknown-field warnings to errors — strict mode. --max-warnings 0 makes any remaining warning fail the job.\n\n```yaml name: Lint docs on: pull_request: paths: - \"docs/**\" - \"**/*.mdx\" jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 - run: bun install - run: npx leadtype lint docs --format github --error-unknown --max-warnings 0 ```","Validate in CI\n\nRun leadtype lint in CI so frontmatter, navigation, and link issues fail PRs before publish.\n\nValidate in CI\n\nOther CI providers\n\nUse --format json for any CI that doesn't speak the GitHub annotations format The JSON output includes per-file violations and summary counts. Pipe it into your provider's reporter, post a PR comment, or upload as an artifact.\n\n```bash npx leadtype lint docs --format json --error-unknown > lint-report.json ```","Validate in CI\n\nRun leadtype lint in CI so frontmatter, navigation, and link issues fail PRs before publish.\n\nValidate in CI\n\nLocal pre-push hook\n\nCatch issues before they reach CI by running lint in a husky pre-push hook Keep it under a second by limiting the scan to changed files when you have many pages. The CLI accepts repeated --ignore globs to skip stale or generated paths.\n\n```bash #!/usr/bin/env sh npx leadtype lint docs --max-warnings 0 ```","Validate in CI\n\nRun leadtype lint in CI so frontmatter, navigation, and link issues fail PRs before publish.\n\nValidate in CI\n\nRun before generate\n\nWhen leadtype lint and leadtype generate both run in the same job, lint first Generate fails noisily on unknown groups or broken includes. Lint fails specifically on content schema problems with file/line context — much easier to debug.\n\n```bash npx leadtype lint docs --error-unknown npx leadtype generate --src . --out public --json ```","Validate in CI\n\nRun leadtype lint in CI so frontmatter, navigation, and link issues fail PRs before publish.\n\nValidate in CI\n\nWhat to fix first\n\nWhen CI fails on a lot of violations, fix them in this order 1. parse-error — frontmatter is broken; nothing else can validate. 2. schema — missing or wrong-typed required fields. 3. unresolved-placeholder — content bug, not a config bug. 4. invalid-link and cross-framework-link — usually a stale link after a docs move. 5. unknown-field — last; either delete the field or extend the schema.","How it works\n\nThe mental model: one MDX source, a remark pipeline, two output modes, three audiences.\n\nHow it works\n\nLeadtype takes one input — a folder of MDX — and produces every shape your docs need to take. This page names every piece so the rest of the docs make sense.","How it works\n\nThe mental model: one MDX source, a remark pipeline, two output modes, three audiences.\n\nHow it works\n\nThe pipeline\n\nThe remark stack is what turns interactive MDX components into agent-readable markdown. JSX gets flattened — a fm fm --> remark fm --> groups remark --> md md --> site_idx md --> search groups --> site_idx groups --> agents_md groups --> nav` ```","How it works\n\nThe mental model: one MDX source, a remark pipeline, two output modes, three audiences.\n\nHow it works\n\nTwo output modes\n\nleadtype generate has two modes that read the same source and emit different shapes Property Type Description Default Required -- -- -- -- -- Site mode default leadtype generate --out public Writes llms.txt, llms-full.txt, docs/search-index.json, docs/sitemap.xml, docs/sitemap.md, docs/robots.txt, docs/agent-readability.json, and docs/\\ .md to a public/ directory your docs website serves. This is what you wire into a Vite, Next.js, Astro, or TanStack Start build. - Optional Bundle mode leadtype generate --bundle --out packages/foo Writes AGENTS.md at the package root and docs/\\ .md beneath it, both with relative paths. Skips llms.txt, llms-full.txt, search, sitemap, robots, and Agent Readability files — those are website-only. Designed for npm tarballs that ship docs alongside the published code. - Optional","How it works\n\nThe mental model: one MDX source, a remark pipeline, two output modes, three audiences.\n\nHow it works\n\nThe artifacts\n\nProperty Type Description Default Required -- -- -- -- -- Markdown .md docs/\\ human site_out -- \"absolute URLs\" --> http_agent site_out -- \"search-index.json\" --> search_ui bundle_out -- \"version-matched AGENTS.md\" --> offline_agent` ```","How it works\n\nThe mental model: one MDX source, a remark pipeline, two output modes, three audiences.\n\nHow it works\n\nVocabulary\n\nA few terms you will see throughout the docs. Property Type Description Default Required -- -- -- -- -- flatten verb Convert an interactive MDX component into a portable markdown equivalent. A \\ site_run src --> bundle_run site_run --> site_out bundle_run --> bundle_out site_out --> humans site_out --> http_agents site_out --> search bundle_out --> offline_agents` ```","Leadtype\n\nOne MDX source. Hosted docs artifacts, package-bundled AGENTS.md, and search output from the same pipeline.\n\nLeadtype\n\nChoose your path\n\nPick the job that matches what you are building. Each path starts with the minimum setup, then links to the lower-level API reference only when you need it. Connect a docs site Add search Ship docs in your package","Leadtype\n\nOne MDX source. Hosted docs artifacts, package-bundled AGENTS.md, and search output from the same pipeline.\n\nLeadtype\n\nWhat you get\n\n1. Write once Author MDX with familiar components — Callout , Tabs , Steps , Mermaid , TypeTable , and others. Add group in frontmatter to place pages in the navigation tree. 2. Run \\ leadtype generate\\ For a website converts MDX to markdown, builds llms.txt plus root llms-full.txt , generates a search index, writes Agent Readability discovery files, and resolves navigation. With --bundle emits AGENTS.md plus per-topic .md files with relative links that still work after npm install. 3. Serve all of it Humans get HTML from your app. HTTP agents get markdown via content negotiation or /llms.txt . Package consumers can point their root AGENTS.md or README at node modules/ cli cli --> bundle bundle --> publish publish --> install install --> consume` ```","Bundle docs into a package\n\nShip agent-readable docs inside an npm tarball — AGENTS.md at the package root plus per-topic .md files.\n\nBundle docs into a package\n\nWhy AGENTS.md, not llms.txt?\n\nllms.txt is a website convention — a file at /llms.txt with absolute URLs that an agent fetches over HTTP. Inside an npm tarball it's the wrong shape every link points at a hosted URL the agent may not be able to reach, and no major coding agent looks for node modules/ 0) { for (const { urlPath, slug } of navigation.unknown) { process.stderr.write(`error: ${urlPath} declares unknown group \"${slug}\".\\n`); } process.exit(1); } await generateAgentsMd({ srcDir: REPO_ROOT, outDir: PACKAGE_ROOT, product: docsConfig.product, groups: docsConfig.groups, }); ```","Bundle docs into a package\n\nShip agent-readable docs inside an npm tarball — AGENTS.md at the package root plus per-topic .md files.\n\nBundle docs into a package\n\nVerify before publishing\n\nnpm pack --dry-run should list AGENTS.md docs/ / .md If AGENTS.md is missing, check files in package.json . If .md files are missing, check the --include / --exclude filters.\n\n```bash npx leadtype generate --bundle --src . --out packages/my-package cd packages/my-package && npm pack --dry-run ```","Bundle docs into a package\n\nShip agent-readable docs inside an npm tarball — AGENTS.md at the package root plus per-topic .md files.\n\nBundle docs into a package\n\nTell consuming projects to use the bundle\n\nAGENTS.md inside your tarball is available at node modules/ When working with the `` library, read the bundled docs in `node_modules//AGENTS.md` first — they're version-matched to the installed package and stay accurate as the library updates. ```","Bundle docs into a package\n\nShip agent-readable docs inside an npm tarball — AGENTS.md at the package root plus per-topic .md files.\n\nBundle docs into a package\n\nWhen to use this\n\nUse this when agents should understand the package from the installed dependency itself — coding agents that don't have web access, IDE assistants, CLI tools, or air-gapped environments. Don't use this if your only goal is a public docs website. For that, see Connect a docs site. You can use both — they read the same source MDX, just emit different shapes.","Bundle docs into a package\n\nShip agent-readable docs inside an npm tarball — AGENTS.md at the package root plus per-topic .md files.\n\nBundle docs into a package\n\nWhat's next\n\nCLI reference LLM files Lint in CI","Quickstart\n\nInstall leadtype, run the hosted-docs pipeline once, and inspect the generated artifacts.\n\nQuickstart\n\nFive minutes from a folder of MDX to generated docs artifacts.","Quickstart\n\nInstall leadtype, run the hosted-docs pipeline once, and inspect the generated artifacts.\n\nQuickstart\n\nInstall\n\nPackage manager Command -- -- npm npm install leadtype pnpm pnpm add leadtype yarn yarn add leadtype bun bun add leadtype leadtype ships a CLI plus focused library entry points. Start with the CLI; use the APIs only when your build needs custom plugin order, filtering, or output paths.","Quickstart\n\nInstall leadtype, run the hosted-docs pipeline once, and inspect the generated artifacts.\n\nQuickstart\n\nAuthor one page\n\nCreate docs/index.mdx in your repo Every page needs a title . Add group when the page should appear in generated navigation and llms.txt sections. See Frontmatter for the full content contract.\n\n```mdx --- title: \"My library\" description: \"What it does in one sentence.\" group: get-started --- # My library Welcome. ```","Quickstart\n\nInstall leadtype, run the hosted-docs pipeline once, and inspect the generated artifacts.\n\nQuickstart\n\nGenerate hosted docs output\n\nThat command reads docs/ .mdx , converts it to markdown, resolves groups, builds search JSON, and writes hosted agent artifacts. Open public/docs/index.md first. It shows what your MDX becomes after the remark component flattening pipeline runs. Then open public/llms.txt to see the hosted routing file that HTTP agents start from. 💡 Tip Working reference apps/example/ in the leadtype repo is the production docs site for these docs. It runs the same pipeline you just ran, on TanStack Start, with markdown content negotiation, sitemap regeneration, and JSON-LD wired up. Clone it when you want a copy-pastable end-to-end setup.\n\n```bash npx leadtype generate \\ --src . \\ --out public \\ --base-url https://example.com ``` ```text public/ ├── llms.txt ├── llms-full.txt └── docs/ ├── index.md ├── llms.txt ├── sitemap.xml ├── sitemap.md ├── robots.txt ├── agent-readability.json ├── search-index.json └── search-content.json ```","Quickstart\n\nInstall leadtype, run the hosted-docs pipeline once, and inspect the generated artifacts.\n\nQuickstart\n\nChoose the next setup step\n\nGoal Next page -- -- Wire the generator into an app build Connect a docs site Render HTML pages and an \"On this page\" sidebar Render MDX and TOC Serve markdown, sitemaps, robots, and JSON-LD for agents Optimize docs for agents Query the generated static search index Add search Publish AGENTS.md inside an npm package Bundle docs into a package Connect a docs site Render MDX and TOC Make the site agent-readable Bundle docs into a package","CLI\n\nleadtype generate and leadtype lint — flags, exit codes, and JSON output.\n\nCLI\n\nTwo commands generate runs the full pipeline, lint validates content. Run leadtype help [options] ```","CLI\n\nleadtype generate and leadtype lint — flags, exit codes, and JSON output.\n\nCLI\n\ngenerate\n\nConvert MDX, then either produce website artifacts default or a package bundle --bundle . Flag Default Description -- -- -- --src ; summary: { filesScanned: number; errors: number; warnings: number; }; }; ```","Lint rules\n\nSchema, link, and navigation checks. CLI and library API.\n\nLint rules\n\nDefault schemas\n\nDocs frontmatter\n\nField Required Type -- -- -- title Yes non-empty string description No string icon No string deprecated No boolean deprecatedReason No string experimental No boolean canary No boolean new No boolean draft No boolean tags No string array group No string or string array availableIn No array of framework, url?, title? full No boolean lastModified and lastAuthor are produced by the converter when --enrich-git is set. Don't author them.","Lint rules\n\nSchema, link, and navigation checks. CLI and library API.\n\nLint rules\n\nDefault schemas\n\nChangelog frontmatter\n\nField Required Type -- -- -- title Yes non-empty string version Yes SemVer string date Yes ISO-8601 or parseable date description No string icon No string type No release , improvement , retired , or deprecation tags No string array canary No boolean authors No string or string array draft No boolean","Lint rules\n\nSchema, link, and navigation checks. CLI and library API.\n\nLint rules\n\nDefault schemas\n\nmeta.json\n\nField Required Type -- -- -- pages Yes string array title No non-empty string root No boolean icon No string defaultOpen No boolean nav.sidebar No section or combined nav.label No string nav.mode No string","Lint rules\n\nSchema, link, and navigation checks. CLI and library API.\n\nLint rules\n\nCustom schemas\n\nPass a Valibot schema to extend or replace the defaults Once you provide a custom schema, unknown-field warnings apply to that schema. Add --error-unknown in CI to keep your contract strict.\n\n```ts import * as v from \"valibot\"; import { lintDocs } from \"leadtype/lint\"; const customFrontmatter = v.object({ title: v.pipe(v.string(), v.minLength(1)), audience: v.picklist([\"beginner\", \"advanced\"]), }); await lintDocs({ srcDir: \"docs\", schemas: { frontmatter: customFrontmatter }, }); ```","Lint rules\n\nSchema, link, and navigation checks. CLI and library API.\n\nLint rules\n\nPractical guidance\n\nRun lint before leadtype generate so content errors fail fast. Use --format github in GitHub Actions and --format json in any other CI. Treat unresolved-placeholder as a content bug first — usually a missing entry in availableIn or a stale URL template. After a docs move, lint and run meta.json updates together; they drift at the same time. For wiring lint into pipelines, see Validate in CI.","LLM files\n\nGenerate llms.txt for hosted websites and AGENTS.md for npm-bundled offline reading.\n\nLLM files\n\nThe leadtype/llm entry point produces four flavors of agent-facing output, all derived from the same docs source generateLlmsTxt — for hosted websites. Emits the /llms.txt convention with root-relative markdown mirror links. generateLLMFullContextFiles — root /llms-full.txt fallback containing all generated markdown docs. Pairs with generateLlmsTxt . generateAgentReadabilityArtifacts — docs-scoped sitemap.xml , sitemap.md , robots.txt , and JSON manifest data that a host app can merge into site-level files. generateAgentsMd — for npm-bundled docs. Emits an AGENTS.md index with relative ./docs/ A library that does one thing well. - Helper that handles the boring parts. - Type-safe by default. - Works in any runtime. ## Best Starting Points - [Documentation](/docs/index.md) - [Quickstart](/docs/quickstart.md) ## Get Started Five-minute happy path and the mental model. - [Quickstart](/docs/quickstart.md): Install and run the pipeline. - [How it works](/docs/how-it-works.md): The mental model. ## Reference CLI flags and conversion APIs. - [CLI](/docs/reference/cli.md): Every flag. ```","LLM files\n\nGenerate llms.txt for hosted websites and AGENTS.md for npm-bundled offline reading.\n\nLLM files\n\nTypical sequence\n\ngenerateLLMFullContextFiles and generateAgentReadabilityArtifacts read from A library that does one thing well. These docs ship inside the package so coding agents can read them offline. Open the topic file you need from the list below — paths are relative to this file. ## Get Started - [Quickstart](./docs/quickstart.md): Install and run the pipeline. - [How it works](./docs/how-it-works.md): The mental model. ## Reference - [CLI](./docs/reference/cli.md): Every flag. ```","LLM files\n\nGenerate llms.txt for hosted websites and AGENTS.md for npm-bundled offline reading.\n\nLLM files\n\nresolveDocsNavigation\n\nSame group-resolution logic the LLM files use, but returns the navigation manifest as a plain object — useful for driving a sidebar UI Write the result to src/generated/docs-nav.json and import it from your sidebar component Now your sidebar can import a static manifest with the same group tree the LLM files use.\n\n```ts const navigation = await resolveDocsNavigation({ srcDir: \".\", baseUrl: \"https://leadtype.dev\", groups: docsConfig.groups, }); if (navigation.unknown.length > 0) { for (const { urlPath, slug } of navigation.unknown) { process.stderr.write(`error: ${urlPath} declares unknown group \"${slug}\".\\n`); } process.exit(1); } ``` ```ts import { mkdir, writeFile } from \"node:fs/promises\"; await mkdir(\"src/generated\", { recursive: true }); await writeFile( \"src/generated/docs-nav.json\", `${JSON.stringify(navigation, null, 2)}\\n` ); ```","LLM files\n\nGenerate llms.txt for hosted websites and AGENTS.md for npm-bundled offline reading.\n\nLLM files\n\nTables of contents\n\nFor the heading slug contract and renderer wiring, see Render MDX and TOC. This section covers the build-time APIs only. resolveDocsNavigation includes a toc array on every page by default. The default range is h2 – h3 , which keeps page-level h1 titles out of sidebars. If you only need TOC data and not the full group tree, call resolveDocsTableOfContents For custom pipelines, extractDocsTableOfContents accepts a markdown or MDX string plus page URL metadata and returns plain JSON. It ignores frontmatter and fenced code blocks, and it uses the same slugifyDocsHeading helper that rendered headings must use to keep id attributes in sync.\n\n```ts const navigation = await resolveDocsNavigation({ srcDir: \".\", baseUrl: \"https://leadtype.dev\", groups: docsConfig.groups, toc: { minLevel: 2, maxLevel: 4 }, }); ``` ```ts const pages = await resolveDocsTableOfContents({ srcDir: \".\", baseUrl: \"https://leadtype.dev\", }); ```","LLM files\n\nGenerate llms.txt for hosted websites and AGENTS.md for npm-bundled offline reading.\n\nLLM files\n\nGroup design\n\nThe groups you pass to these APIs come from docs.config.ts . Two principles Use groups for routing, not sharding. Groups organize llms.txt , navigation, search metadata, and AGENTS.md . The root llms-full.txt remains the broad fallback. Write group descriptions for routing, not flavor text. Agents read those descriptions to decide which pages to load. \"How to install and run\" beats \"Welcome to our guides!\"","LLM files\n\nGenerate llms.txt for hosted websites and AGENTS.md for npm-bundled offline reading.\n\nLLM files\n\nBase URL precedence\n\nPass baseUrl explicitly, or use environment variables for layered fallback The package-specific LEADTYPE AGENT BASE URL lets each package override an org-wide default. BASE URL covers most CI/deployment platforms, and a final hardcoded fallback keeps local builds working without env setup.\n\n```ts const baseUrl = process.env.LEADTYPE_AGENT_BASE_URL || process.env.BASE_URL || process.env.PORTLESS_URL || \"https://leadtype.dev\"; ```","Remark plugins\n\nThe default plugin stack that flattens MDX components into markdown.\n\nRemark plugins\n\nThe remark stack is what turns interactive MDX into agent-readable markdown. Imports get stripped first, placeholders get resolved, then each named component is flattened into a markdown equivalent. Order matters.\n\n```ts import { defaultRemarkPlugins, remarkInclude, remarkTypeTableToMarkdown, } from \"leadtype/remark\"; ```","Remark plugins\n\nThe default plugin stack that flattens MDX components into markdown.\n\nRemark plugins\n\nThe default stack\n\ndefaultRemarkPlugins runs the stack in this order 1. remarkRemoveImports — strip MDX import and export statements. 2. remarkRemoveJsxComments — strip / ... / JSX comments. 3. remarkResolveDocPlaceholders — replace framework and similar placeholders in URLs. 4. remarkAudienceToMarkdown — include ri --> rj --> rd --> rau --> rs --> rc --> rcd --> rdt --> rm --> rct --> rst --> rt --> rtt --> ra --> rts --> rft --> rp --> re --> out` ```","Remark plugins\n\nThe default plugin stack that flattens MDX components into markdown.\n\nRemark plugins\n\nThe default stack\n\n p !== remarkTypeTableToMarkdown), [remarkTypeTableToMarkdown, { basePath: process.cwd() }], ]; ``` ```mdx ```","Remark plugins\n\nThe default plugin stack that flattens MDX components into markdown.\n\nRemark plugins\n\nPlugin selection rules\n\nUse defaultRemarkPlugins for any agent-facing or LLM output. Add remarkInclude when docs are composed from shared fragments. Use individual plugins only when you intentionally want to omit a flattener e.g. you don't use /docs/search-index.json /docs/search-content.json ```","Search\n\nStatic search index, runtime helpers, and source-grounded answer streaming.\n\nSearch\n\nRuntime search\n\nThe runtime is edge-safe — no Node APIs, works on Vercel, Cloudflare, and anywhere else Results include heading paths, hash URLs, and snippets ready for a search UI. Search is still local and dependency-free, but it is not exact-token only. Query terms expand through lightweight stemming, prefix matches, typo-tolerant fallbacks, and a small built-in synonym map. Exact matches keep the highest weight so API names and config keys stay precise. Pass synonyms when your docs use product-specific vocabulary\n\n```ts import { searchDocs, type DocsSearchIndex, type DocsSearchContentStore, } from \"leadtype/search\"; import indexJson from \"../public/docs/search-index.json\"; import contentJson from \"../public/docs/search-content.json\"; const results = searchDocs( indexJson as DocsSearchIndex, \"tabs install\", { content: contentJson as DocsSearchContentStore } ); ``` ```ts const results = searchDocs(index, \"starter\", { content, synonyms: { starter: [\"quickstart\", \"getting started\"], }, }); ```","Search\n\nStatic search index, runtime helpers, and source-grounded answer streaming.\n\nSearch\n\nReading docs at runtime\n\nThe same index doubles as a virtual filesystem. Three readers, picked by what you have Use readDocsContentFile when you need the entire page for context links . Use readDocsContentChunk when a search result already named the right heading.\n\n```ts import { listDocsContentFiles, readDocsContentFile, readDocsContentChunk, } from \"leadtype/search\"; const allFiles = listDocsContentFiles(index); const wholePage = readDocsContentFile(index, \"guides/quickstart\", content); const oneChunk = readDocsContentChunk(index, \"chunk-0\", content); ```","Search\n\nStatic search index, runtime helpers, and source-grounded answer streaming.\n\nSearch\n\nSource-grounded answers\n\ncreateAnswerContext turns a query plus retrieved chunks into a system and prompt you pass to any model The system message instructs the model to answer only from the retrieved context, cite sources with 1 -style references, and say so when the context is insufficient.\n\n```ts import { createAnswerContext } from \"leadtype/search\"; const context = createAnswerContext(index, \"how do I run lint?\", { content, productName: \"My Library\", }); // → { system, prompt, sources } ```","Search\n\nStatic search index, runtime helpers, and source-grounded answer streaming.\n\nSearch\n\nStreaming via provider entry points\n\nThree thin wrappers around createAnswerContext that stream a Response and surface sources separately. Use one matching your runtime response is a plain text Response. sources is metadata for citation links — display it separately, don't embed it in the streamed answer. For TanStack, pass an explicit adapter . For Cloudflare, build one with createCloudflareDocsAdapter provider, model, options binding env.AI.gateway \"docs\" .\n\n```ts import { streamDocsAnswer } from \"leadtype/search/vercel\"; // Vercel AI SDK / AI Gateway import { streamDocsAnswer } from \"leadtype/search/tanstack\"; // TanStack AI import { streamDocsAnswer } from \"leadtype/search/cloudflare\"; // Cloudflare AI Gateway / Workers AI ``` ```ts const { response, sources } = streamDocsAnswer({ index, content, query, model: \"openai/gpt-5.5\", productName: \"My Library\", }); ```","Search\n\nStatic search index, runtime helpers, and source-grounded answer streaming.\n\nSearch\n\nBash tool adapters\n\nWhen you want an agent to explore docs with shell commands instead of receiving pre-selected chunks The adapter exposes a read-only virtual /docs filesystem with ls , cat , find , grep , and rg . Network commands, code execution, and writes are disabled. Use createDocsBashTool for Vercel AI SDK tool sets and createDocsBashTools for TanStack-compatible tools over the same filesystem.\n\n```ts import { createDocsBashTool, createDocsBashTools } from \"leadtype/search/bash\"; const { tools, instructions } = await createDocsBashTool(index, content); ```","Search\n\nStatic search index, runtime helpers, and source-grounded answer streaming.\n\nSearch\n\nAbuse guards\n\nReusable utilities for the request path Helper Purpose -- -- validateDocsQuery Trim and cap query text. readJsonWithLimit Reject oversized JSON bodies before parse. getClientIdentifier Read common proxy IP headers. createMemoryRateLimiter Implements RateLimiter for demos. The in-memory limiter is fine for demos. Production apps should adapt the RateLimiter interface to a shared store — Redis, Vercel KV, Cloudflare KV, or Durable Objects.","Search\n\nStatic search index, runtime helpers, and source-grounded answer streaming.\n\nSearch\n\nWhen to add embeddings\n\nStart with the local index. It is static, cheap, edge-safe, and fast for exact API names, config keys, error messages, and paths. Add embeddings only when Users search with vocabulary that doesn't match the docs e.g. \"make it faster\" matching a \"performance optimization\" page . Your docs grow past tens of thousands of chunks and the cold-start memory hit becomes noticeable. Even then, keep the lexical index for exact matches and layer embeddings on top — they're complementary, not replacements."]}
+{"version":2,"generatedAt":"2026-05-13T06:50:55.273Z","chunks":["Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nLeadtype does not ship UI components. Your docs app owns runtime rendering, styling, and accessibility — it only has to honor a small naming contract so the remark pipeline can flatten each component into markdown for agents, search, and llms-full.txt .","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nWhy flatten at all?\n\nInteractive MDX components like ./shared/session-flow.mdx ``` ```mdx ``` ```mdx ``` ```mdx This content can be reused in multiple pages. ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nEach section below shows the authored MDX and a live render.","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nCallout\n\nWraps supporting context, warnings, or tips. Variants change styling but flatten identically into a blockquote. ℹ️ Info Heads up Callouts wrap supporting context, warnings, or tips. The remark pipeline flattens them into blockquotes so agents still see the content. ⚠️ Warning Don't do this Variants like warning, success, error, and tip change the styling but flatten identically.\n\n```tsx Body content goes here. ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nCards\n\nA grid of short, linked entry points. Flattens to a bullet list of links. Convert Remark Search\n\n```tsx ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nSteps\n\nNumbered walkthroughs. Flattens to an ordered list with bold step titles. 1. Author docs in MDX Use the components in this list as authoring affordances. 2. Run the conversion leadtype generate writes flattened markdown to public/docs/ . 3. Serve both formats HTML for humans, .md for agents — same URL, content negotiated by the Accept header.\n\n```tsx Use the components in this list.`leadtype generate` writes flattened markdown. ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nTabs\n\nGroup equivalent content. Flattens to bold headings followed by content so agents do not need a JSX-aware renderer to read every variant. tanstack-start Use a Vite middleware dev/preview and a Nitro middleware prod to negotiate the Accept header. next-js Wire content negotiation in middleware.ts and serve .md from a route handler. vite A configureServer middleware is enough for static deployments where .md files live in public/ .\n\n```tsx ……… ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nCommandTabs\n\nPackage-manager-aware install or run commands. Flattens to a markdown table with one row per manager. Use mode=\"install\" when command is a package name, mode=\"run\" when command is a CLI name, and mode=\"create\" for starter commands. Use the commands prop for exact per-manager overrides. Package manager Command -- -- npm npm install leadtype pnpm pnpm add leadtype yarn yarn add leadtype bun bun add leadtype Package manager Command -- -- npm npx leadtype lint pnpm pnpm dlx leadtype lint yarn yarn dlx leadtype lint bun bunx leadtype lint\n\n```tsx ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nPrompt\n\nDisplays an agent-ready prompt with a copy action. Flattening preserves the prompt body as a fenced prompt block so copied instructions also survive in .md , root llms-full.txt , and bundled AGENTS.md output. Copy prompt for your coding agent Use this after generating artifacts.\n\n```tsx Inspect `public/docs/agent-readability.json`, then wire markdown responses before the HTML docs route. ``` ```prompt Inspect `public/docs/agent-readability.json`, then wire markdown responses before the HTML docs route. ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nAudience\n\nSplits browser-only and agent-only guidance without forking the page. Human content renders in the docs UI and is omitted from markdown output; agent content is hidden in the browser and included in generated markdown. This sentence appears only in generated markdown for agents.\n\n```tsx Click the robot icon in the header.Read generated markdown before editing runtime routes. ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nFileTree\n\nShows project structure in guides and release instructions. Flattening emits a fenced text tree so agents can read the same hierarchy without JSX.\n\n```tsx ``` ```text public/ ├── llms.txt └── docs/ └── index.md ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nAccordion\n\nCollapsible details for secondary content. Flattening ignores open/closed state and emits every item — accordions are not a place to hide content from agents. When should I use accordions? Use them for supporting details, troubleshooting notes, and optional reference material. Closed content is still flattened by the remark pipeline. Are accordions a good place to hide content from LLMs? No. Conversion ignores the open/closed state and emits everything inside.\n\n```tsx Use them for supporting details and optional reference material. ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nTopicSwitcher\n\nNavigation across equivalent docs topics — frameworks, SDKs, runtimes, deployment targets, product areas. Reader-facing only; it does not automatically read LLM topic config. Framework React — React integration Vue — Vue integration Svelte — Svelte integration\n\n```tsx ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nTypeTable and ExtractedTypeTable\n\nTypeTable is for explicit prop or type rows you already know. ExtractedTypeTable reads a TypeScript file at conversion time and extracts the table from a named type — keep its path stable. Property Type Description Default Required -- -- -- -- -- title string Heading rendered above the callout body. - ✅ Required variant CalloutVariant Visual treatment for the callout. info Optional deprecated \\ \\ boolean\\ \\ deprecated Marks the row as deprecated. false Optional\n\n```tsx ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nExample\n\nData-driven preview and source examples. The host component receives code as data; add file loaders or dynamic imports outside leadtype when an example needs app-specific behavior.\n\n```tsx The host app owns styling and runtime components while leadtype owns conversion. ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nComponent reference\n\nMermaid\n\nDiagrams authored as plain text. Renders client-side as interactive SVG. Flattening preserves the source as a fenced mermaid block so other tools can render the diagram from the markdown copy.\n\n```tsx |remark| Markdown Markdown -->|llms.txt| Agents`} /> ``` ```mermaid graph LR MDX -->|remark| Markdown Markdown -->|search index| API Markdown -->|llms.txt| Agents ```","Components\n\nMDX components the pipeline knows how to flatten into agent-readable markdown.\n\nComponents\n\nGuidelines\n\nKeep runtime components in your docs app. Leadtype stays out of UI. Keep component names stable. Renaming groups: [authoring, docs-site, reference]\"] page1[\"page A group: authoring\"] page2[\"page B group: docs-site\"] page3[\"page C group: docs-site\"] resolver[\"group resolver\"] nav[\"navigation tree\"] llms[\"llms.txt sections\"] agents[\"AGENTS.md sections\"] cfg --> resolver page1 --> resolver page2 --> resolver page3 --> resolver resolver --> nav resolver --> llms resolver --> agents ```","Frontmatter\n\nRequired fields, group semantics, and how authored MDX becomes a navigation tree.\n\nFrontmatter\n\nHow groups become a nav tree\n\nNested groups\n\nDeclare children in the config to build deeper trees A page sets group remote-source and lands in that nested slot. Only leaf groups no children directly contain pages; non-leaf groups are headings only.\n\n```ts { slug: \"docs-site\", title: \"Build a Docs Site\", children: [ { slug: \"remote-source\", title: \"Remote source\" }, { slug: \"build-a-docs-site\", title: \"Build a docs site\" }, ], } ```","Frontmatter\n\nRequired fields, group semantics, and how authored MDX becomes a navigation tree.\n\nFrontmatter\n\nOptional fields\n\nThe default lint schema also accepts Property Type Description Default Required -- -- -- -- -- icon string Icon name resolved by your sidebar component. - Optional deprecated boolean Marks the page as deprecated in nav and search. - Optional deprecatedReason string Short message paired with deprecated. - Optional experimental boolean Marks the page as experimental. - Optional canary boolean Hides from stable channels. - Optional new boolean Highlights the page as recently added. - Optional draft boolean Excludes from generation entirely. - Optional tags string\\ Free-form tags for search facets. - Optional availableIn Array\\<\\ framework, url?, title? Cross-framework availability map for TopicSwitcher pages. - Optional full boolean Layout hint for docs UIs that support full-width pages. - Optional lastModified and lastAuthor are filled in automatically when you pass --enrich-git to the CLI. Don't author them by hand.","Frontmatter\n\nRequired fields, group semantics, and how authored MDX becomes a navigation tree.\n\nFrontmatter\n\nLint rules\n\nleadtype lint enforces the schema, so violations surface in CI before they reach a build. The relevant rules schema — a required field is missing or has the wrong type. unknown-field — a top-level field isn't in the schema warn by default; --error-unknown to fail . parse-error — frontmatter or meta.json doesn't parse. invalid-link — a /docs/... link points to a route that doesn't exist. unresolved-placeholder — a doc URL still contains an unresolved framework placeholder. cross-framework-link — a framework-scoped page links to another framework's docs. See Lint rules for the full reference and how to extend the schema.","Frontmatter\n\nRequired fields, group semantics, and how authored MDX becomes a navigation tree.\n\nFrontmatter\n\nWhat this gives you\n\nOnce frontmatter is consistent, the rest of the pipeline works without per-page configuration. The same group value drives The sidebar position The llms.txt section Search metadata and AGENTS.md grouping The search filtering UI if you build one Cross-framework link checks in lint One field, one source of truth.","Add search\n\nGenerate a static docs search index, query it at runtime, and optionally stream source-grounded answers.\n\nAdd search\n\nLeadtype search is static by default. Build time produces two JSON files; runtime code imports or fetches those files and queries them without a database.","Add search\n\nGenerate a static docs search index, query it at runtime, and optionally stream source-grounded answers.\n\nAdd search\n\nGenerate the files\n\nleadtype generate writes search files in site mode If you run the pipeline from scripts, call the search generator after conversion This writes The index contains compact ranking data. The content store contains the text used for excerpts and answer context.\n\n```bash npx leadtype generate --src . --out public --base-url https://example.com ``` ```ts import { generateDocsSearchFiles } from \"leadtype/search/node\"; await generateDocsSearchFiles({ outDir: \"public\", baseUrl: \"https://example.com\", }); ``` ```txt public/docs/search-index.json public/docs/search-content.json ```","Add search\n\nGenerate a static docs search index, query it at runtime, and optionally stream source-grounded answers.\n\nAdd search\n\nQuery at runtime\n\nResults include page URLs, heading paths, hash URLs, and snippets. Render them in your own search UI.\n\n```ts import { searchDocs, type DocsSearchContentStore, type DocsSearchIndex, } from \"leadtype/search\"; import contentJson from \"../public/docs/search-content.json\"; import indexJson from \"../public/docs/search-index.json\"; const index = indexJson as DocsSearchIndex; const content = contentJson as DocsSearchContentStore; const results = searchDocs(index, \"run lint\", { content }); ```","Add search\n\nGenerate a static docs search index, query it at runtime, and optionally stream source-grounded answers.\n\nAdd search\n\nAdd vocabulary aliases\n\nSearch starts with lexical matching, stemming, prefix matches, typo-tolerant fallbacks, and a small built-in synonym map. Add product-specific synonyms only when users search with words your docs do not use\n\n```ts const results = searchDocs(index, \"starter\", { content, synonyms: { starter: [\"quickstart\", \"getting started\"], }, }); ```","Add search\n\nGenerate a static docs search index, query it at runtime, and optionally stream source-grounded answers.\n\nAdd search\n\nOptional AI answers\n\nUse source-grounded answers only after basic search works. Leadtype retrieves chunks from the static index, builds a constrained prompt, and leaves model choice to the provider entry point you import Display sources next to the streamed response. Do not ask the model to answer from memory; the answer context is built from retrieved docs chunks.\n\n```ts import { streamDocsAnswer } from \"leadtype/search/vercel\"; const { response, sources } = streamDocsAnswer({ index, content, query: \"How do I run docs lint in CI?\", model: \"openai/gpt-5.5\", productName: \"My Library\", }); ```","Add search\n\nGenerate a static docs search index, query it at runtime, and optionally stream source-grounded answers.\n\nAdd search\n\nGuard the endpoint\n\nFor API routes that accept user queries, use the request helpers from leadtype/search validateDocsQuery to trim and cap query text. readJsonWithLimit to reject oversized JSON bodies. getClientIdentifier to read common proxy IP headers. createMemoryRateLimiter for demos. Production apps should adapt the rate limiter interface to a shared store such as Redis, Vercel KV, Cloudflare KV, or Durable Objects.","Add search\n\nGenerate a static docs search index, query it at runtime, and optionally stream source-grounded answers.\n\nAdd search\n\nVerify\n\npublic/docs/search-index.json and public/docs/search-content.json exist and are non-empty. Searching for an exact API name returns the expected reference page. Searching for a guide phrase returns a result with a section hash. AI answers cite sources from the returned sources metadata.","Build a docs site\n\nPick the right leadtype integration shape for your docs app, and what each path gives you.\n\nBuild a docs site\n\nLeadtype offers two integration shapes for a docs site. Pick the one that fits how your app is built — both produce the same content, just at different layers of your stack.","Build a docs site\n\nPick the right leadtype integration shape for your docs app, and what each path gives you.\n\nBuild a docs site\n\nPick your path\n\nPath When to choose What you wire -- -- -- Source primitive Most cases. You're building a Next, Vite, Astro, or Fumadocs app and compile MDX with your bundler. createDocsSource or leadtype/fumadocs + mdxSourcePlugins Static artifacts Your runtime needs flat files on disk CDN-only deploy, static export, agent-only consumption, multi-app sharing . leadtype generate CLI in your build script The two paths are not mutually exclusive — you can use the source primitive for your UI and still run leadtype generate for the llms.txt and agent-readability artifacts.\n\n```mermaid flowchart LR src[\"source MDX docs/*.mdx + meta.json\"] primitive[\"createDocsSource() (leadtype/mdx + leadtype/fumadocs)\"] cli[\"leadtype generate (CLI)\"] app[\"docs app (Next, Astro, Vite, Fumadocs)\"] artifacts[\"public/ llms.txt · docs/*.md search-index · sitemap\"] src --> primitive --> app src --> cli --> artifacts --> app ```","Build a docs site\n\nPick the right leadtype integration shape for your docs app, and what each path gives you.\n\nBuild a docs site\n\nSource primitive the common path\n\nIf your docs app compiles MDX through a bundler, use the source primitive. It gives your runtime loadPage slug returning frontmatter + AST + serialized markdown + TOC getNavigation returning the resolved group tree buildSearchIndex returning a static search index resolveInclude for programmatic partial loading → Use the source primitive — generic recipe → Integrate with Fumadocs — first-party adapter","Build a docs site\n\nPick the right leadtype integration shape for your docs app, and what each path gives you.\n\nBuild a docs site\n\nStatic artifacts the CLI path\n\nIf your runtime needs files on disk — for a CDN-only deploy, a static export, a separate agent-only service, or to share artifacts across multiple sibling apps — run the CLI. It writes public/llms.txt and public/llms-full.txt public/docs/ .md markdown mirrors public/docs/search-index.json + search-content.json public/docs/sitemap.xml , sitemap.md , robots.txt , agent-readability.json → Generate static artifacts — CLI workflow","Build a docs site\n\nPick the right leadtype integration shape for your docs app, and what each path gives you.\n\nBuild a docs site\n\nAdd the cross-cutting features\n\nWhichever path you pick, the same follow-on guides apply Add search — local search index + optional source-grounded answers Optimize docs for agents — markdown responses, llms.txt, discovery files Validate in CI — lint frontmatter, meta.json, internal links","Build a docs site\n\nPick the right leadtype integration shape for your docs app, and what each path gives you.\n\nBuild a docs site\n\nConfigure product and groups\n\nBoth paths read the same docs/docs.config.ts . Source repos own this file so groups and product metadata version with the docs Pages declare group in frontmatter; the config declares titles, order, and descriptions. See Frontmatter for the page-level schema.\n\n```ts import { defineDocsConfig } from \"leadtype\"; export default defineDocsConfig({ product: { name: \"c15t\", summary: \"Consent infrastructure for modern web apps.\", bullets: [\"Framework integrations.\", \"Consent primitives.\", \"Audit-friendly docs.\"], bestStartingPoints: [{ urlPath: \"/docs\" }, { urlPath: \"/docs/quickstart\" }], }, groups: [ { slug: \"get-started\", title: \"Get Started\" }, { slug: \"guides\", title: \"Guides\" }, { slug: \"reference\", title: \"Reference\" }, ], }); ```","Generate static artifacts\n\nRun leadtype generate from your build pipeline to write llms.txt, markdown mirrors, search index, sitemap, and agent-readability files to disk.\n\nGenerate static artifacts\n\nUse this path when your runtime needs files on disk — a CDN-only deploy, a static export, a separate agent-only service, or multiple sibling apps sharing one corpus. The leadtype generate CLI walks your MDX source and writes a complete set of files into public/ . For app runtimes that compile MDX through a bundler Next, Astro, Vite, Fumadocs , prefer the source primitive — it skips the disk round-trip.","Generate static artifacts\n\nRun leadtype generate from your build pipeline to write llms.txt, markdown mirrors, search index, sitemap, and agent-readability files to disk.\n\nGenerate static artifacts\n\nThe flow\n\n```mermaid flowchart LR repo[\"source repo docs/*.mdx\"] clone[\"checkout or clone .docs-src/c15t\"] lint[\"leadtype lint\"] generate[\"leadtype generate\"] public[\"public/ llms.txt · llms-full.txt docs/*.md search · agent metadata\"] app[\"any consumer (docs app, agent, CDN)\"] repo --> clone --> lint --> generate --> public --> app ```","Generate static artifacts\n\nRun leadtype generate from your build pipeline to write llms.txt, markdown mirrors, search index, sitemap, and agent-readability files to disk.\n\nGenerate static artifacts\n\nFetch the source repo\n\nIn CI, check out the docs source before the build. For a public repo, a shallow clone is enough For private repos, use your CI platform's checkout action or a read-only deploy key. The important part is that leadtype receives a normal filesystem path whose root contains docs/ .\n\n```bash rm -rf .docs-src/c15t git clone --depth 1 https://github.com/c15t/c15t .docs-src/c15t ```","Generate static artifacts\n\nRun leadtype generate from your build pipeline to write llms.txt, markdown mirrors, search index, sitemap, and agent-readability files to disk.\n\nGenerate static artifacts\n\nLint before generate\n\nRun lint against the fetched docs before writing generated output. Lint fails with file and line context, which is easier to debug than a later app build using stale artifacts\n\n```bash npx leadtype lint .docs-src/c15t/docs \\ --format github \\ --error-unknown \\ --max-warnings 0 ```","Generate static artifacts\n\nRun leadtype generate from your build pipeline to write llms.txt, markdown mirrors, search index, sitemap, and agent-readability files to disk.\n\nGenerate static artifacts\n\nGenerate\n\nPoint --src at the fetched repo root and --out at the directory you'll serve That command writes public/llms.txt and public/llms-full.txt public/docs/ .md public/docs/search-index.json and public/docs/search-content.json public/docs/sitemap.xml , sitemap.md , robots.txt , and agent-readability.json Use --json in CI so automation can record resolved groups, output files, filters, and search index stats.\n\n```bash npx leadtype generate \\ --src .docs-src/c15t \\ --out public \\ --base-url https://docs.example.com \\ --json ```","Generate static artifacts\n\nRun leadtype generate from your build pipeline to write llms.txt, markdown mirrors, search index, sitemap, and agent-readability files to disk.\n\nGenerate static artifacts\n\nMulti-source mounting\n\nSome projects keep docs and release notes side by side instead of putting everything under docs/ Repeat --docs-dir to include those folders in the same generated corpus By default, extra sources are mounted under /docs/ {title ?
{title}
: null}
{children}
); } ```","Integrate with Fumadocs\n\nWire leadtype's content layer into a fumadocs app for nav, search, and includes.\n\nIntegrate with Fumadocs\n\nLoad a page from a server component\n\nIf you prefer fumadocs's built-in page resolution, call source.getPage slug and import the source .mdx directly through fumadocs-mdx as you normally would — the mdxSourcePlugins preset will resolve includes during MDX compilation.\n\n```tsx title=\"app/docs/[[...slug]]/page.tsx\" import { source } from \"@/content/source\"; import { MDXRemote } from \"next-mdx-remote/rsc\"; export default async function Page({ params, }: { params: Promise<{ slug?: string[] }>; }) { const { slug } = await params; const page = await source.loadPage(slug ?? []); if (!page) { notFound(); } return (
{page.title}
); } ```","Integrate with Fumadocs\n\nWire leadtype's content layer into a fumadocs app for nav, search, and includes.\n\nIntegrate with Fumadocs\n\nAdd search\n\nBuild a search index from the same source For provider-specific search Vercel AI, TanStack, Cloudflare , wire the bundle into a leadtype/search/ adapter. See Search.\n\n```ts title=\"app/api/search/route.ts\" import { source } from \"@/content/source\"; const bundle = await source.leadtype.buildSearchIndex(); export async function GET() { return Response.json(bundle.index); } ```","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\nUse this guide when you already have a docs site and want agents to find, fetch, attribute, and cite the same content humans read in the browser. Leadtype handles the generated files. Your app wires those files into routing and HTML. The default output shape is based on the repo's agent evals. See Evals for the benchmark summary and the open question around larger-corpus llms-full.txt scaling.","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\nWhat good looks like\n\nAn agent-readable docs site has four layers 1. Discovery files /llms.txt , /sitemap.xml , /sitemap.md , and /robots.txt tell agents what exists and where to start. 2. Markdown retrieval Each docs page has a markdown mirror at /docs/page.md , and agent requests to /docs/page can receive markdown instead of HTML. 3. Structured HTML metadata Human HTML pages include JSON-LD, canonical links, and markdown alternate links so agents can extract page identity without guessing from the DOM. 4. Attribution metadata Markdown responses include canonical url and last updated frontmatter so copied content keeps its source and freshness.","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\n1. Generate the artifacts\n\nRun the site-mode pipeline before your app build This writes the docs-scoped files under public/docs/ and the top-level public/llms.txt The generated agent-readability.json manifest is the bridge between build-time content and runtime requests. It contains page URLs, markdown mirror paths, titles, descriptions, group navigation, and freshness dates.\n\n```bash npx leadtype generate \\ --src . \\ --out public \\ --base-url https://leadtype.dev \\ --name \"My product\" \\ --summary \"One sentence about the product.\" ``` ```txt public/ ├── llms.txt ├── llms-full.txt └── docs/ ├── index.md ├── quickstart.md ├── llms.txt ├── sitemap.xml ├── sitemap.md ├── robots.txt └── agent-readability.json ```","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\n2. Add one middleware\n\nPut the agent-readable routes before your HTML docs route. This Node/Bun example handles root discovery files, docs-scoped discovery files, direct .md URLs, and Accept text/markdown requests in one place If you also have marketing, blog, changelog, or product pages, pass them through the optional pages field — the regenerator merges them into the rebased output The other generated artifacts — /llms.txt , /docs/llms.txt , /llms-full.txt , /docs/agent-readability.json — use root-relative links and serve fine as static files straight from public/ . Keep the docs-scoped versions too /docs/sitemap.xml etc. . Audits and agents may request both /sitemap.xml and /docs/sitemap.xml , especially when the audited URL is /docs .\n\n```ts import { readFile } from \"node:fs/promises\"; import { join } from \"node:path\"; import manifestJson from \"../public/docs/agent-readability.json\" with { type: \"json\", }; import { createAgentMarkdownResponse, createRobotsTxtResponse, createSitemapMarkdownResponse, createSitemapXmlResponse, type AgentReadabilityManifest, type MarkdownMirrorTarget, } from \"leadtype/llm/readability\"; const manifest = { ...manifestJson, version: 1, } as AgentReadabilityManifest; async function readMarkdownFile( target: MarkdownMirrorTarget ): Promise { try { return await readFile(join(process.cwd(), \"public\", target.filePath), \"utf8\"); } catch (error) { if ( typeof error === \"object\" && error !== null && \"code\" in error && (error.code === \"ENOENT\" || error.code === \"ENOTDIR\") ) { return null; } throw error; } } export async function handleDocsRequest( request: Request ): Promise { if (request.method !== \"GET\" && request.method !== \"HEAD\") { return null; } const url = new URL(request.url); const requestOrigin = url.origin; switch (url.pathname) { case \"/sitemap.xml\": case \"/docs/sitemap.xml\": return createSitemapXmlResponse({ manifest, requestOrigin }); case","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\n2. Add one middleware\n\nstOrigin = url.origin; switch (url.pathname) { case \"/sitemap.xml\": case \"/docs/sitemap.xml\": return createSitemapXmlResponse({ manifest, requestOrigin }); case \"/sitemap.md\": case \"/docs/sitemap.md\": return createSitemapMarkdownResponse({ manifest, requestOrigin }); case \"/robots.txt\": return createRobotsTxtResponse({ manifest, requestOrigin }); case \"/docs/robots.txt\": return createRobotsTxtResponse({ manifest, requestOrigin, sitemapUrlPath: \"/docs/sitemap.xml\", }); default: return createAgentMarkdownResponse({ urlPath: url.pathname, method: request.method, headers: Object.fromEntries(request.headers), manifest, readMarkdownFile, requestOrigin, }); } } ``` ```ts return createSitemapXmlResponse({ manifest, requestOrigin, pages: [...manifest.pages, ...marketingPages, ...blogPages], }); ```","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\n3. Add JSON-LD to docs pages\n\nUse the manifest entry for the current page and render Schema.org JSON-LD into the HTML head Use renderJsonLd page, manifest if your framework has a typed metadata API. Use renderJsonLdScript page, manifest if your framework expects an HTML string. Also add canonical and markdown alternate links The JSON-LD gives agents the page title, description, canonical URL, last modified date, and breadcrumbs without scraping your rendered layout.\n\n```ts import agentManifest from \"../public/docs/agent-readability.json\"; import { renderJsonLd, renderJsonLdScript } from \"leadtype/llm/readability\"; const page = agentManifest.pages.find( (entry) => entry.urlPath === \"/docs/quickstart\" ); if (page) { const jsonLd = renderJsonLd(page, agentManifest); const script = renderJsonLdScript(page, agentManifest); } ``` ```html ```","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\n4. Return markdown to agents\n\nThe middleware above uses createAgentMarkdownResponse . It returns a Web Response or null when the path is not an agent-oriented markdown request and handles Accept text/markdown and Accept text/plain content negotiation q-values respected . Known AI user-agent headers GPTBot, ClaudeBot, Bingbot, AmazonBot, MetaExternalAgent, PerplexityBot, MistralBot, AppleBot, ByteSpider, YouBot, … . Direct .md URLs such as /docs/quickstart.md . canonical url and last updated frontmatter aliases injected automatically. 200 markdown responses for missing docs pages, so agents do not discard the body. Content-Type text/markdown; charset=utf-8 , Vary Accept , User-Agent , Link <… ; rel=\"canonical\" , Cache-Control public, max-age=300, must-revalidate . readMarkdownFile may be sync or async. In Node/Bun, read from disk. In Cloudflare, fetch from KV/R2 or an asset binding. In Vercel Edge, fetch from the deployment's static asset URL. Put that logic wherever your framework can intercept docs requests before its HTML route Framework/runtime Where it usually goes -- -- TanStack Start / nitro server/middleware/agent-readability.ts h3 .","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\n4. Return markdown to agents\n\nn intercept docs requests before its HTML route Framework/runtime Where it usually goes -- -- TanStack Start / nitro server/middleware/agent-readability.ts h3 . One middleware handles both the markdown response and the sitemap/robots regenerators — runs in dev, preview, and prod. Nuxt server/middleware/agent-readability.ts h3 — same shape as the TanStack Start example. Next.js middleware.ts Edge or a catch-all route handler before the docs page. Astro An endpoint at pages/docs/ ...slug .md.ts or astro middleware . Cloudflare Workers/Pages Worker fetch handler with KV/R2 asset binding for the markdown reader. Express/Hono/Fastify Middleware before the docs HTML route. Tip if you keep static sitemap.xml / sitemap.md / robots.txt files in your build output, your framework's static handler may serve them before your middleware can rebase URLs to the live origin. Either delete the static copies after the build so the middleware always runs or make sure your middleware is registered ahead of static-asset serving. Do not rewrite llms.txt , sitemap.xml , sitemap.md , robots.txt , llms-full.txt , or agent-readability.json to page markdown. The helper leaves those artifact paths alone.","Optimize docs for agents\n\nSet up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site.\n\nOptimize docs for agents\n\n4. Return markdown to agents\n\nWhy the sitemap and robots responses are regenerated, not static\n\nsitemap.xml 's }) { const { slug = [] } = await params; const page = await source.loadPage(slug); if (!page) notFound(); return (
{page.title}
{page.description ?
{page.description}
: null} ); } export async function generateStaticParams() { const pages = await source.listPages(); return pages.map((page) => ({ slug: page.slug })); } ```","Use the source primitive\n\nWire createDocsSource into Next, Astro, Vite, Nuxt, SvelteKit, or any MDX-aware bundler. Same primitive, multiple host shapes.\n\nUse the source primitive\n\nWire into your framework\n\nAstro Content Collections\n\nUse 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.\n\n```ts title=\"astro.config.mjs\" import { defineConfig } from \"astro/config\"; import mdx from \"@astrojs/mdx\"; import { mdxSourcePlugins } from \"leadtype/mdx\"; export default defineConfig({ integrations: [mdx({ remarkPlugins: [...mdxSourcePlugins] })], }); ```","Use the source primitive\n\nWire createDocsSource into Next, Astro, Vite, Nuxt, SvelteKit, or any MDX-aware bundler. Same primitive, multiple host shapes.\n\nUse the source primitive\n\nWire into your framework\n\nVite + @mdx-js/rollup works for Vue, Solid, Svelte starters\n\n```ts title=\"vite.config.ts\" import mdx from \"@mdx-js/rollup\"; import { mdxSourcePlugins } from \"leadtype/mdx\"; export default { plugins: [ mdx({ remarkPlugins: [...mdxSourcePlugins] }), // ...your framework plugin: viteReact / vue / solid / svelte ], }; ```","Use the source primitive\n\nWire createDocsSource into Next, Astro, Vite, Nuxt, SvelteKit, or any MDX-aware bundler. Same primitive, multiple host shapes.\n\nUse the source primitive\n\nWire into your framework\n\nNuxt\n\n```ts title=\"nuxt.config.ts\" import { mdxSourcePlugins } from \"leadtype/mdx\"; export default defineNuxtConfig({ modules: [\"@nuxtjs/mdc\"], mdc: { remarkPlugins: { ...mdxSourcePlugins } }, }); ```","Use the source primitive\n\nWire createDocsSource into Next, Astro, Vite, Nuxt, SvelteKit, or any MDX-aware bundler. Same primitive, multiple host shapes.\n\nUse the source primitive\n\nWire into your framework\n\nSvelteKit + mdsvex\n\n```ts title=\"svelte.config.js\" import { mdsvex } from \"mdsvex\"; import { mdxSourcePlugins } from \"leadtype/mdx\"; export default { extensions: [\".svelte\", \".svx\", \".mdx\"], preprocess: mdsvex({ remarkPlugins: [...mdxSourcePlugins] }), }; ```","Use the source primitive\n\nWire createDocsSource into Next, Astro, Vite, Nuxt, SvelteKit, or any MDX-aware bundler. Same primitive, multiple host shapes.\n\nUse the source primitive\n\nWire into your framework\n\nPattern for any other host\n\nIf your framework's MDX integration accepts a remark plugin list, leadtype works. Three pieces every time 1. Add mdxSourcePlugins to the remark list so ( ), // ... Tabs, Tab, Steps, Step, Cards, Card, TypeTable, etc. }; ```","Use the source primitive\n\nWire createDocsSource into Next, Astro, Vite, Nuxt, SvelteKit, or any MDX-aware bundler. Same primitive, multiple host shapes.\n\nUse the source primitive\n\nBuild the sidebar from navigation\n\nEach page carries a toc field DocsTableOfContentsItem you can render as an \"On this page\" rail.\n\n```tsx title=\"components/sidebar.tsx\" import { source } from \"@/lib/source\"; export async function Sidebar({ currentUrlPath }: { currentUrlPath: string }) { const navigation = await source.getNavigation(); return ( ); } ```","Use the source primitive\n\nWire createDocsSource into Next, Astro, Vite, Nuxt, SvelteKit, or any MDX-aware bundler. Same primitive, multiple host shapes.\n\nUse the source primitive\n\nMatch heading slugs\n\nsource.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.\n\n```tsx import { slugifyDocsHeading } from \"leadtype/llm/readability\"; function textFromChildren(children: unknown): string { if (typeof children === \"string\" || typeof children === \"number\") { return String(children); } if (Array.isArray(children)) return children.map(textFromChildren).join(\"\"); // (recurse into React elements as needed) return \"\"; } const Heading2 = ({ children, id, ...props }: React.HTMLAttributes) => { const headingId = id ?? slugifyDocsHeading(textFromChildren(children)); return
{children}
; }; ```","Use the source primitive\n\nWire createDocsSource into Next, Astro, Vite, Nuxt, SvelteKit, or any MDX-aware bundler. Same primitive, multiple host shapes.\n\nUse the source primitive\n\nBuild a search index\n\nFor provider-specific search Vercel AI, TanStack, Cloudflare , feed the bundle into a leadtype/search/ adapter — see Add search.\n\n```tsx title=\"app/api/search/route.ts\" import { source } from \"@/lib/source\"; const bundle = await source.buildSearchIndex(); export async function GET() { return Response.json(bundle.index); } ```","Use the source primitive\n\nWire createDocsSource into Next, Astro, Vite, Nuxt, SvelteKit, or any MDX-aware bundler. Same primitive, multiple host shapes.\n\nUse the source primitive\n\nTroubleshooting\n\n lint-report.json ```","Validate in CI\n\nRun leadtype lint in CI so frontmatter, navigation, and link issues fail PRs before publish.\n\nValidate in CI\n\nLocal pre-push hook\n\nCatch issues before they reach CI by running lint in a husky pre-push hook Keep it under a second by limiting the scan to changed files when you have many pages. The CLI accepts repeated --ignore globs to skip stale or generated paths.\n\n```bash #!/usr/bin/env sh npx leadtype lint docs --max-warnings 0 ```","Validate in CI\n\nRun leadtype lint in CI so frontmatter, navigation, and link issues fail PRs before publish.\n\nValidate in CI\n\nRun before generate\n\nWhen leadtype lint and leadtype generate both run in the same job, lint first Generate fails noisily on unknown groups or broken includes. Lint fails specifically on content schema problems with file/line context — much easier to debug.\n\n```bash npx leadtype lint docs --error-unknown npx leadtype generate --src . --out public --json ```","Validate in CI\n\nRun leadtype lint in CI so frontmatter, navigation, and link issues fail PRs before publish.\n\nValidate in CI\n\nWhat to fix first\n\nWhen CI fails on a lot of violations, fix them in this order 1. parse-error — frontmatter is broken; nothing else can validate. 2. schema — missing or wrong-typed required fields. 3. unresolved-placeholder — content bug, not a config bug. 4. invalid-link and cross-framework-link — usually a stale link after a docs move. 5. unknown-field — last; either delete the field or extend the schema.","How it works\n\nThe mental model: one MDX source, a remark pipeline, two output modes, three audiences.\n\nHow it works\n\nLeadtype takes one input — a folder of MDX — and produces every shape your docs need to take. This page names every piece so the rest of the docs make sense.","How it works\n\nThe mental model: one MDX source, a remark pipeline, two output modes, three audiences.\n\nHow it works\n\nThe pipeline\n\nThe remark stack is what turns interactive MDX components into agent-readable markdown. JSX gets flattened — a title · description · group · body\"] fm[\"frontmatter parser\"] remark[\"remark plugin stack (strip imports → flatten components)\"] groups[\"group resolver (nav tree from frontmatter)\"] md[\"docs/*.md\"] site_idx[\"llms.txt · llms-full.txt sitemap · robots · manifest (website mode only)\"] search[\"search-index.json · search-content.json (website mode only)\"] agents_md[\"AGENTS.md (--bundle mode only)\"] nav[\"navigation manifest (group → page)\"] src --> fm fm --> remark fm --> groups remark --> md md --> site_idx md --> search groups --> site_idx groups --> agents_md groups --> nav ```","How it works\n\nThe mental model: one MDX source, a remark pipeline, two output modes, three audiences.\n\nHow it works\n\nTwo output modes\n\nleadtype generate has two modes that read the same source and emit different shapes Property Type Description Default Required -- -- -- -- -- Site mode default leadtype generate --out public Writes llms.txt, llms-full.txt, docs/search-index.json, docs/sitemap.xml, docs/sitemap.md, docs/robots.txt, docs/agent-readability.json, and docs/\\ .md to a public/ directory your docs website serves. This is what you wire into a Vite, Next.js, Astro, or TanStack Start build. - Optional Bundle mode leadtype generate --bundle --out packages/foo Writes AGENTS.md at the package root and docs/\\ .md beneath it, both with relative paths. Skips llms.txt, llms-full.txt, search, sitemap, robots, and Agent Readability files — those are website-only. Designed for npm tarballs that ship docs alongside the published code. - Optional","How it works\n\nThe mental model: one MDX source, a remark pipeline, two output modes, three audiences.\n\nHow it works\n\nThe artifacts\n\nProperty Type Description Default Required -- -- -- -- -- Markdown .md docs/\\public/*\"] bundle_out[\"bundle mode node_modules/<pkg>/*\"] human[\"Humans (browser)\"] http_agent[\"HTTP agents (fetch /llms.txt or Accept: text/markdown)\"] search_ui[\"Search UI AI answers\"] offline_agent[\"Coding agents (Claude Code, Codex, Cursor, Copilot, …)\"] site_out -- \"HTML render of MDX\" --> human site_out -- \"absolute URLs\" --> http_agent site_out -- \"search-index.json\" --> search_ui bundle_out -- \"version-matched AGENTS.md\" --> offline_agent ```","How it works\n\nThe mental model: one MDX source, a remark pipeline, two output modes, three audiences.\n\nHow it works\n\nVocabulary\n\nA few terms you will see throughout the docs. Property Type Description Default Required -- -- -- -- -- flatten verb Convert an interactive MDX component into a portable markdown equivalent. A \\(your source)\"] site_run[\"leadtype generate\"] bundle_run[\"leadtype generate --bundle\"] site_out[\"public/ llms.txt · llms-full.txt docs/*.md · sitemap agent-readability.json\"] bundle_out[\"packages/<name>/ AGENTS.md · docs/*.md\"] humans[\"Humans (browser)\"] http_agents[\"HTTP agents (via /llms.txt or Accept: text/markdown)\"] search[\"Search UI AI answers\"] offline_agents[\"Coding agents can read version-matched node_modules/<pkg>/AGENTS.md\"] src --> site_run src --> bundle_run site_run --> site_out bundle_run --> bundle_out site_out --> humans site_out --> http_agents site_out --> search bundle_out --> offline_agents ```","Leadtype\n\nOne MDX source. Hosted docs artifacts, package-bundled AGENTS.md, and search output from the same pipeline.\n\nLeadtype\n\nStart here\n\nQuickstart → — three steps to a working source primitive, then plug it into your framework. Or skip ahead Build a docs site compares every integration path side-by-side.","Leadtype\n\nOne MDX source. Hosted docs artifacts, package-bundled AGENTS.md, and search output from the same pipeline.\n\nLeadtype\n\nWhat leadtype produces\n\nA source primitive for your app llms.txt, sitemaps, agent metadata AGENTS.md for npm packages","Leadtype\n\nOne MDX source. Hosted docs artifacts, package-bundled AGENTS.md, and search output from the same pipeline.\n\nLeadtype\n\nNext\n\nNew here? Read the Quickstart — three steps to a working source. Want the mental model first? Read How it works for the pipeline diagram and the names of every artifact it produces. Comparing tools? See Methodology for how leadtype differs from Fumadocs, Starlight, and Mintlify.","Methodology\n\nHow leadtype differs from Fumadocs, Starlight, and Mintlify.\n\nMethodology\n\nLeadtype is a docs pipeline, not a docs website framework . It produces the artifacts a docs site needs markdown, llms.txt, search index, navigation and stays out of routing, layout, and theming.","Methodology\n\nHow leadtype differs from Fumadocs, Starlight, and Mintlify.\n\nMethodology\n\nThe short version\n\nTool What it gives you -- -- Fumadocs A React docs framework Next.js, TanStack Start, React Router, Waku . Supports llms.txt and content negotiation via framework route handlers. Starlight An Astro docs site framework. llms.txt via the starlight-llms-txt community plugin not built-in ; static client-side search via Pagefind. Mintlify A hosted docs SaaS with an optional headless Astro mode that still calls Mintlify's search and assistant APIs . Leadtype The portable content layer behind any of the above. Choose a website framework when the main job is publishing a polished docs UI quickly. Consider a hosted platform if you want managed publishing, search, analytics, and AI features and accept that service dependency. Opt for leadtype when you need to own the generated docs artifacts framework-agnostic markdown, navigation, search, llms.txt , a root llms-full.txt fallback, and optional AGENTS.md package bundles that ship inside npm tarballs.","Methodology\n\nHow leadtype differs from Fumadocs, Starlight, and Mintlify.\n\nMethodology\n\nWhat leadtype owns\n\nThe MDX tag contract — typed prop shapes for (your repo)\"] cli[\"leadtype generate --bundle --out packages/<name>\"] bundle[\"packages/<name>/ AGENTS.md docs/*.md\"] publish[\"npm publish\"] install[\"npm install <name>\"] consume[\"node_modules/<name>/ AGENTS.md → docs/*.md version-matched offline docs\"] src --> cli cli --> bundle bundle --> publish publish --> install install --> consume ```","Bundle docs into a package\n\nShip agent-readable docs inside an npm tarball — AGENTS.md at the package root plus per-topic .md files.\n\nBundle docs into a package\n\nWhy AGENTS.md, not llms.txt?\n\nllms.txt is a website convention — a file at /llms.txt with absolute URLs that an agent fetches over HTTP. Inside an npm tarball it's the wrong shape every link points at a hosted URL the agent may not be able to reach, and no major coding agent looks for node modules/ 0) { for (const { urlPath, slug } of navigation.unknown) { process.stderr.write(`error: ${urlPath} declares unknown group \"${slug}\".\\n`); } process.exit(1); } await generateAgentsMd({ srcDir: REPO_ROOT, outDir: PACKAGE_ROOT, product: docsConfig.product, groups: docsConfig.groups, }); ```","Bundle docs into a package\n\nShip agent-readable docs inside an npm tarball — AGENTS.md at the package root plus per-topic .md files.\n\nBundle docs into a package\n\nVerify before publishing\n\nnpm pack --dry-run should list AGENTS.md docs/ / .md If AGENTS.md is missing, check files in package.json . If .md files are missing, check the --include / --exclude filters.\n\n```bash npx leadtype generate --bundle --src . --out packages/my-package cd packages/my-package && npm pack --dry-run ```","Bundle docs into a package\n\nShip agent-readable docs inside an npm tarball — AGENTS.md at the package root plus per-topic .md files.\n\nBundle docs into a package\n\nTell consuming projects to use the bundle\n\nAGENTS.md inside your tarball is available at node modules/ When working with the `` library, read the bundled docs in `node_modules//AGENTS.md` first — they're version-matched to the installed package and stay accurate as the library updates. ```","Bundle docs into a package\n\nShip agent-readable docs inside an npm tarball — AGENTS.md at the package root plus per-topic .md files.\n\nBundle docs into a package\n\nWhen to use this\n\nUse this when agents should understand the package from the installed dependency itself — coding agents that don't have web access, IDE assistants, CLI tools, or air-gapped environments. Don't use this if your only goal is a public docs website. For that, see Build a docs site. You can use both — they read the same source MDX, just emit different shapes.","Bundle docs into a package\n\nShip agent-readable docs inside an npm tarball — AGENTS.md at the package root plus per-topic .md files.\n\nBundle docs into a package\n\nWhat's next\n\nCLI reference LLM files Lint in CI","Quickstart\n\nInstall leadtype, author your first MDX page, and create a source. Then plug it into whatever framework you're using.\n\nQuickstart\n\nThree steps to a working source primitive. Then plug it into your framework — Next, Fumadocs, Astro, Vite + Vue/Solid/Svelte, Nuxt, SvelteKit — using one of the recipes below.","Quickstart\n\nInstall leadtype, author your first MDX page, and create a source. Then plug it into whatever framework you're using.\n\nQuickstart\n\nInstall\n\nPackage manager Command -- -- npm npm install leadtype pnpm pnpm add leadtype yarn yarn add leadtype bun bun add leadtype","Quickstart\n\nInstall leadtype, author your first MDX page, and create a source. Then plug it into whatever framework you're using.\n\nQuickstart\n\nAuthor one page\n\nEvery page needs a title . Add group when the page should appear in generated navigation and llms.txt sections. See Frontmatter for the full content contract.\n\n```mdx title=\"content/docs/index.mdx\" --- title: \"My library\" description: \"What it does in one sentence.\" --- # My library Welcome. ```","Quickstart\n\nInstall leadtype, author your first MDX page, and create a source. Then plug it into whatever framework you're using.\n\nQuickstart\n\nCreate the source\n\nThat's the framework-neutral primitive. You can now call source.loadPage slug — resolved markdown + AST + frontmatter + TOC source.listPages — every page's slug, urlPath, and metadata source.getNavigation — grouped sidebar tree source.buildSearchIndex — static search bundle source.resolveInclude specifier — standalone include resolver\n\n```ts title=\"lib/source.ts\" import { createDocsSource } from \"leadtype\"; export const source = await createDocsSource({ contentDir: \"./content/docs\", baseUrl: \"https://example.com\", }); ```","Quickstart\n\nInstall leadtype, author your first MDX page, and create a source. Then plug it into whatever framework you're using.\n\nQuickstart\n\nPlug it into your framework\n\nPick the recipe that matches your stack. Each one shows the wiring on top of the same createDocsSource you just set up. Next App Router Fumadocs Astro Content Collections Vite + Vue / Solid / Svelte Nuxt SvelteKit","Quickstart\n\nInstall leadtype, author your first MDX page, and create a source. Then plug it into whatever framework you're using.\n\nQuickstart\n\nOr write static artifacts to disk\n\nSome pipelines need flat files — CDN-only deploys, static exports, agent-only services, multiple sibling apps sharing one corpus. Use the CLI That writes llms.txt , llms-full.txt , docs/ .md , search index, sitemap, and agent-readability.json to disk. See Generate static artifacts for the full flow.\n\n```sh npx leadtype generate --src . --out public --base-url https://example.com ```","Quickstart\n\nInstall leadtype, author your first MDX page, and create a source. Then plug it into whatever framework you're using.\n\nQuickstart\n\nNext steps\n\nGoal Page -- -- Compare every integration shape side-by-side Build a docs site Implement custom MDX tags Callout, Tabs, Steps, … leadtype/mdx Add search Add search Validate frontmatter and links in CI Validate in CI Serve markdown, sitemaps, robots, and JSON-LD for agents Optimize docs for agents Publish AGENTS.md inside an npm package Bundle docs into a package","CLI\n\nleadtype generate and leadtype lint — flags, exit codes, and JSON output.\n\nCLI\n\nTwo commands generate runs the full pipeline, lint validates content. Run leadtype help [options] ```","CLI\n\nleadtype generate and leadtype lint — flags, exit codes, and JSON output.\n\nCLI\n\ngenerate\n\nConvert MDX, then either produce website artifacts default or a package bundle --bundle . Flag Default Description -- -- -- --src ; summary: { filesScanned: number; errors: number; warnings: number; }; }; ```","Lint rules\n\nSchema, link, and navigation checks. CLI and library API.\n\nLint rules\n\nDefault schemas\n\nDocs frontmatter\n\nField Required Type -- -- -- title Yes non-empty string description No string icon No string deprecated No boolean deprecatedReason No string experimental No boolean canary No boolean new No boolean draft No boolean tags No string array group No string or string array availableIn No array of framework, url?, title? full No boolean lastModified and lastAuthor are produced by the converter when --enrich-git is set. Don't author them.","Lint rules\n\nSchema, link, and navigation checks. CLI and library API.\n\nLint rules\n\nDefault schemas\n\nChangelog frontmatter\n\nField Required Type -- -- -- title Yes non-empty string version Yes SemVer string date Yes ISO-8601 or parseable date description No string icon No string type No release , improvement , retired , or deprecation tags No string array canary No boolean authors No string or string array draft No boolean","Lint rules\n\nSchema, link, and navigation checks. CLI and library API.\n\nLint rules\n\nDefault schemas\n\nmeta.json\n\nField Required Type -- -- -- pages Yes string array title No non-empty string root No boolean icon No string defaultOpen No boolean nav.sidebar No section or combined nav.label No string nav.mode No string","Lint rules\n\nSchema, link, and navigation checks. CLI and library API.\n\nLint rules\n\nCustom schemas\n\nPass a Valibot schema to extend or replace the defaults Once you provide a custom schema, unknown-field warnings apply to that schema. Add --error-unknown in CI to keep your contract strict.\n\n```ts import * as v from \"valibot\"; import { lintDocs } from \"leadtype/lint\"; const customFrontmatter = v.object({ title: v.pipe(v.string(), v.minLength(1)), audience: v.picklist([\"beginner\", \"advanced\"]), }); await lintDocs({ srcDir: \"docs\", schemas: { frontmatter: customFrontmatter }, }); ```","Lint rules\n\nSchema, link, and navigation checks. CLI and library API.\n\nLint rules\n\nPractical guidance\n\nRun lint before leadtype generate so content errors fail fast. Use --format github in GitHub Actions and --format json in any other CI. Treat unresolved-placeholder as a content bug first — usually a missing entry in availableIn or a stale URL template. After a docs move, lint and run meta.json updates together; they drift at the same time. For wiring lint into pipelines, see Validate in CI.","LLM files\n\nGenerate llms.txt for hosted websites and AGENTS.md for npm-bundled offline reading.\n\nLLM files\n\nThe leadtype/llm entry point produces four flavors of agent-facing output, all derived from the same docs source generateLlmsTxt — for hosted websites. Emits the /llms.txt convention with root-relative markdown mirror links. generateLLMFullContextFiles — root /llms-full.txt fallback containing all generated markdown docs. Pairs with generateLlmsTxt . generateAgentReadabilityArtifacts — docs-scoped sitemap.xml , sitemap.md , robots.txt , and JSON manifest data that a host app can merge into site-level files. generateAgentsMd — for npm-bundled docs. Emits an AGENTS.md index with relative ./docs/ A library that does one thing well. - Helper that handles the boring parts. - Type-safe by default. - Works in any runtime. ## Best Starting Points - [Documentation](/docs/index.md) - [Quickstart](/docs/quickstart.md) ## Get Started Five-minute happy path and the mental model. - [Quickstart](/docs/quickstart.md): Install and run the pipeline. - [How it works](/docs/how-it-works.md): The mental model. ## Reference CLI flags and conversion APIs. - [CLI](/docs/reference/cli.md): Every flag. ```","LLM files\n\nGenerate llms.txt for hosted websites and AGENTS.md for npm-bundled offline reading.\n\nLLM files\n\nTypical sequence\n\ngenerateLLMFullContextFiles and generateAgentReadabilityArtifacts read from A library that does one thing well. These docs ship inside the package so coding agents can read them offline. Open the topic file you need from the list below — paths are relative to this file. ## Get Started - [Quickstart](./docs/quickstart.md): Install and run the pipeline. - [How it works](./docs/how-it-works.md): The mental model. ## Reference - [CLI](./docs/reference/cli.md): Every flag. ```","LLM files\n\nGenerate llms.txt for hosted websites and AGENTS.md for npm-bundled offline reading.\n\nLLM files\n\nresolveDocsNavigation\n\nSame group-resolution logic the LLM files use, but returns the navigation manifest as a plain object — useful for driving a sidebar UI Write the result to src/generated/docs-nav.json and import it from your sidebar component Now your sidebar can import a static manifest with the same group tree the LLM files use.\n\n```ts const navigation = await resolveDocsNavigation({ srcDir: \".\", baseUrl: \"https://leadtype.dev\", groups: docsConfig.groups, }); if (navigation.unknown.length > 0) { for (const { urlPath, slug } of navigation.unknown) { process.stderr.write(`error: ${urlPath} declares unknown group \"${slug}\".\\n`); } process.exit(1); } ``` ```ts import { mkdir, writeFile } from \"node:fs/promises\"; await mkdir(\"src/generated\", { recursive: true }); await writeFile( \"src/generated/docs-nav.json\", `${JSON.stringify(navigation, null, 2)}\\n` ); ```","LLM files\n\nGenerate llms.txt for hosted websites and AGENTS.md for npm-bundled offline reading.\n\nLLM files\n\nTables of contents\n\nFor the heading slug contract and renderer wiring, see Use the source primitive. This section covers the build-time APIs only. resolveDocsNavigation includes a toc array on every page by default. The default range is h2 – h3 , which keeps page-level h1 titles out of sidebars. If you only need TOC data and not the full group tree, call resolveDocsTableOfContents For custom pipelines, extractDocsTableOfContents accepts a markdown or MDX string plus page URL metadata and returns plain JSON. It ignores frontmatter and fenced code blocks, and it uses the same slugifyDocsHeading helper that rendered headings must use to keep id attributes in sync.\n\n```ts const navigation = await resolveDocsNavigation({ srcDir: \".\", baseUrl: \"https://leadtype.dev\", groups: docsConfig.groups, toc: { minLevel: 2, maxLevel: 4 }, }); ``` ```ts const pages = await resolveDocsTableOfContents({ srcDir: \".\", baseUrl: \"https://leadtype.dev\", }); ```","LLM files\n\nGenerate llms.txt for hosted websites and AGENTS.md for npm-bundled offline reading.\n\nLLM files\n\nGroup design\n\nThe groups you pass to these APIs come from docs.config.ts . Two principles Use groups for routing, not sharding. Groups organize llms.txt , navigation, search metadata, and AGENTS.md . The root llms-full.txt remains the broad fallback. Write group descriptions for routing, not flavor text. Agents read those descriptions to decide which pages to load. \"How to install and run\" beats \"Welcome to our guides!\"","LLM files\n\nGenerate llms.txt for hosted websites and AGENTS.md for npm-bundled offline reading.\n\nLLM files\n\nBase URL precedence\n\nPass baseUrl explicitly, or use environment variables for layered fallback The package-specific LEADTYPE AGENT BASE URL lets each package override an org-wide default. BASE URL covers most CI/deployment platforms, and a final hardcoded fallback keeps local builds working without env setup.\n\n```ts const baseUrl = process.env.LEADTYPE_AGENT_BASE_URL || process.env.BASE_URL || process.env.PORTLESS_URL || \"https://leadtype.dev\"; ```","leadtype/mdx\n\nTag type contracts and the build-time source preset for consumers rendering MDX themselves.\n\nleadtype/mdx\n\nThe leadtype/mdx subpath is the consumer-facing MDX surface — everything you need to compile leadtype-authored MDX in your own renderer fumadocs, Next App Router, Vite + @mdx-js, Astro content collections . It exports three things 1. Tag type contracts — typed prop shapes for every custom MDX tag. 2. mdxSourcePlugins — a remark preset that performs build-time resolution only expand includes, resolve & HTMLAttributes & { children?: ReactNode }; export function Callout({ variant, title, children, ...rest }: ReactCalloutProps) { return ( ); } ```","leadtype/mdx\n\nTag type contracts and the build-time source preset for consumers rendering MDX themselves.\n\nleadtype/mdx\n\nFramework-neutral by design\n\nVue\n\n```vue ```","leadtype/mdx\n\nTag type contracts and the build-time source preset for consumers rendering MDX themselves.\n\nleadtype/mdx\n\nFramework-neutral by design\n\nSvelte\n\n```svelte ```","leadtype/mdx\n\nTag type contracts and the build-time source preset for consumers rendering MDX themselves.\n\nleadtype/mdx\n\nFramework-neutral by design\n\nSolid\n\n```tsx import type { CalloutProps } from \"leadtype/mdx\"; import type { JSX } from \"solid-js\"; type SolidCalloutProps = Omit & { children?: JSX.Element; }; export function Callout(props: SolidCalloutProps) { return ( ); } ```","leadtype/mdx\n\nTag type contracts and the build-time source preset for consumers rendering MDX themselves.\n\nleadtype/mdx\n\nFramework-neutral by design\n\nAstro\n\n```astro --- import type { CalloutProps } from \"leadtype/mdx\"; type Props = Omit; const { variant = \"info\", title } = Astro.props as Props; --- ```","leadtype/mdx\n\nTag type contracts and the build-time source preset for consumers rendering MDX themselves.\n\nleadtype/mdx\n\nFramework-neutral by design\n\nFull type inventory\n\nEvery prop name is part of the 1.0 contract — bumping a shape is a breaking change. New optional props are minor.\n\n```ts import type { // Layout AudienceProps, AudienceTarget, SectionProps, DetailsProps, // Callouts CalloutProps, CalloutVariant, CalloutTypeAlias, // Navigation / structure TabsProps, TabProps, StepsProps, StepProps, AccordionProps, AccordionItemProps, // Cards / topics CardsProps, CardProps, CardVariant, TopicSwitcherProps, TopicSwitcherItem, // File tree FileTreeProps, FolderProps, FileProps, // Code / commands CommandTabsProps, CommandMode, PackageManager, ExampleProps, ExampleSourceFile, PromptProps, // Type tables TypeTableProps, TypeTableProperty, ExtractedTypeTableProps, // Diagrams MermaidProps, } from \"leadtype/mdx\"; ```","leadtype/mdx\n\nTag type contracts and the build-time source preset for consumers rendering MDX themselves.\n\nleadtype/mdx\n\nFramework-neutral by design\n\nBuild-time only {title ?
: null}
+
+
+
+
+
+
+ );
+}
+
+export async function generateStaticParams() {
+ const pages = await leadtypeSource.listPages();
+ return pages.map((page) => ({ slug: page.slug }));
+}
+
+export async function generateMetadata({ params }: { params: PageParams }) {
+ const { slug = [] } = await params;
+ const page = await leadtypeSource.loadPage(slug);
+ if (!page) {
+ return {};
+ }
+ return {
+ title: `${page.title} — c15t docs`,
+ description: page.description,
+ };
+}
diff --git a/apps/fumadocs-example/app/docs/layout.tsx b/apps/fumadocs-example/app/docs/layout.tsx
new file mode 100644
index 0000000..2fbab4c
--- /dev/null
+++ b/apps/fumadocs-example/app/docs/layout.tsx
@@ -0,0 +1,57 @@
+import { DocsLayout } from "fumadocs-ui/layouts/docs";
+import type { ReactNode } from "react";
+import { FrameworkSwitcher } from "@/lib/framework-switcher";
+import { leadtypeSource, source } from "@/lib/source";
+
+// Build at render time on the server: every page that exists, so the
+// switcher can fall back to /quickstart when the sibling page is missing.
+const allPages = await leadtypeSource.listPages();
+const knownRoutes = new Set(allPages.map((page) => page.urlPath));
+
+/**
+ * Top "tabs" that group docs by audience. Each tab points at its section's
+ * landing route and matches every URL inside that section. fumadocs renders
+ * these as a switcher above the sidebar.
+ */
+const sidebarTabs = [
+ {
+ title: "Frontend",
+ description: "SDKs, components, hooks, and styling",
+ url: "/docs/frameworks/next/quickstart",
+ urls: new Set([
+ "/docs/frameworks/next",
+ "/docs/frameworks/react",
+ "/docs/frameworks/javascript",
+ ]),
+ },
+ {
+ title: "Integrations",
+ description: "Tag managers, analytics, and ad platforms",
+ url: "/docs/integrations/overview",
+ urls: new Set(["/docs/integrations"]),
+ },
+ {
+ title: "Self Host",
+ description: "Backend setup, deployment, and API reference",
+ url: "/docs/self-host/quickstart",
+ urls: new Set(["/docs/self-host"]),
+ },
+];
+
+const navLinks = [{ text: "Changelog", url: "/changelog", external: false }];
+
+export default function DocsRouteLayout({ children }: { children: ReactNode }) {
+ return (
+ ,
+ }}
+ tree={source.pageTree}
+ >
+ {children}
+
+ );
+}
diff --git a/apps/fumadocs-example/app/global.css b/apps/fumadocs-example/app/global.css
new file mode 100644
index 0000000..8aa4042
--- /dev/null
+++ b/apps/fumadocs-example/app/global.css
@@ -0,0 +1,9 @@
+@import "tailwindcss";
+@import "fumadocs-ui/css/neutral.css";
+@import "fumadocs-ui/css/preset.css";
+
+/* Tailwind v4 only scans the files you point it at. fumadocs-ui ships its
+ classes inside its compiled JS — without this @source line, Tailwind won't
+ emit any of fumadocs-ui's utility classes and the layout falls back to
+ unstyled text. */
+@source "../node_modules/fumadocs-ui/dist/**/*.js";
diff --git a/apps/fumadocs-example/app/layout.tsx b/apps/fumadocs-example/app/layout.tsx
new file mode 100644
index 0000000..a2c7c12
--- /dev/null
+++ b/apps/fumadocs-example/app/layout.tsx
@@ -0,0 +1,19 @@
+import { RootProvider } from "fumadocs-ui/provider";
+import type { ReactNode } from "react";
+import "./global.css";
+
+export default function RootLayout({ children }: { children: ReactNode }) {
+ return (
+
+
+ {children}
+
+
+ );
+}
+
+export const metadata = {
+ title: "c15t — fumadocs + leadtype",
+ description:
+ "c15t consent-management docs rendered through fumadocs-ui with leadtype as the source layer.",
+};
diff --git a/apps/fumadocs-example/app/page.tsx b/apps/fumadocs-example/app/page.tsx
new file mode 100644
index 0000000..d085b75
--- /dev/null
+++ b/apps/fumadocs-example/app/page.tsx
@@ -0,0 +1,21 @@
+import Link from "next/link";
+
+export default function HomePage() {
+ return (
+
+
c15t docs
+
+ Rendered through fumadocs-ui with leadtype as the source layer.
+ c15t's authored MDX (including <include>{" "}
+ partials and <ExtractedTypeTable> components) is
+ resolved at build time by mdxSourcePlugins.
+
+
+ Open the Next.js quickstart →
+
+
+ );
+}
diff --git a/apps/fumadocs-example/css.d.ts b/apps/fumadocs-example/css.d.ts
new file mode 100644
index 0000000..cbe652d
--- /dev/null
+++ b/apps/fumadocs-example/css.d.ts
@@ -0,0 +1 @@
+declare module "*.css";
diff --git a/apps/fumadocs-example/lib/framework-switcher.tsx b/apps/fumadocs-example/lib/framework-switcher.tsx
new file mode 100644
index 0000000..d5594a3
--- /dev/null
+++ b/apps/fumadocs-example/lib/framework-switcher.tsx
@@ -0,0 +1,75 @@
+"use client";
+
+import { usePathname, useRouter } from "next/navigation";
+
+const frameworks = [
+ { id: "next", label: "Next.js" },
+ { id: "react", label: "React" },
+ { id: "javascript", label: "JavaScript" },
+] as const;
+
+type FrameworkId = (typeof frameworks)[number]["id"];
+
+const frameworkRoutePattern =
+ /^\/docs\/frameworks\/(next|react|javascript)(\/(.*))?$/;
+
+function suffixFromPath(pathname: string): {
+ framework: FrameworkId;
+ suffix: string;
+} | null {
+ const match = pathname.match(frameworkRoutePattern);
+ if (!match) {
+ return null;
+ }
+ return {
+ framework: match[1] as FrameworkId,
+ suffix: match[3] ?? "quickstart",
+ };
+}
+
+interface FrameworkSwitcherProps {
+ /** Routes that exist for each framework; passed in from a server component. */
+ knownRoutes: Set;
+}
+
+export function FrameworkSwitcher({ knownRoutes }: FrameworkSwitcherProps) {
+ const pathname = usePathname();
+ const router = useRouter();
+ const current = suffixFromPath(pathname);
+
+ // Only show on /docs/frameworks/* routes.
+ if (!current) {
+ return null;
+ }
+
+ return (
+
+
+
+ );
+}
+```
+
+If you prefer fumadocs's built-in page resolution, call `source.getPage(slug)` and import the source `.mdx` directly through fumadocs-mdx as you normally would — the `mdxSourcePlugins` preset will resolve includes during MDX compilation.
+
+## Add search
+
+Build a search index from the same source:
+
+```ts title="app/api/search/route.ts"
+import { source } from "@/content/source";
+
+const bundle = await source.leadtype.buildSearchIndex();
+
+export async function GET() {
+ return Response.json(bundle.index);
+}
+```
+
+For provider-specific search (Vercel AI, TanStack, Cloudflare), wire the bundle into a `leadtype/search/*` adapter. See [Search](/docs/build/add-search).
diff --git a/docs/build/optimize-docs-for-agents.mdx b/docs/build/optimize-docs-for-agents.mdx
index ee7d83f..d8540bb 100644
--- a/docs/build/optimize-docs-for-agents.mdx
+++ b/docs/build/optimize-docs-for-agents.mdx
@@ -2,6 +2,7 @@
title: "Optimize docs for agents"
description: "Set up llms.txt, markdown mirrors, JSON-LD, sitemaps, robots.txt, and audit checks for an agent-readable docs site."
group: docs-site
+order: 50
---
# Optimize docs for agents
@@ -206,7 +207,7 @@ Put that logic wherever your framework can intercept docs requests before its HT
| Framework/runtime | Where it usually goes |
| --- | --- |
-| TanStack Start / nitro | `server/middleware/agent-readability.ts` (h3). One middleware handles both the markdown response and the sitemap/robots regenerators — runs in dev, preview, and prod. See [`apps/example/server/middleware/agent-readability.ts`](https://github.com/inthhq/leadtype/blob/main/apps/example/server/middleware/agent-readability.ts) for the canonical reference. |
+| TanStack Start / nitro | `server/middleware/agent-readability.ts` (h3). One middleware handles both the markdown response and the sitemap/robots regenerators — runs in dev, preview, and prod. |
| Nuxt | `server/middleware/agent-readability.ts` (h3) — same shape as the TanStack Start example. |
| Next.js | `middleware.ts` (Edge) or a catch-all route handler before the docs page. |
| Astro | An endpoint at `pages/docs/[...slug].md.ts` or `astro:middleware`. |
diff --git a/docs/build/render-mdx-and-toc.mdx b/docs/build/render-mdx-and-toc.mdx
deleted file mode 100644
index bb4102c..0000000
--- a/docs/build/render-mdx-and-toc.mdx
+++ /dev/null
@@ -1,94 +0,0 @@
----
-title: "Render MDX and TOC"
-description: "Set up runtime MDX components, stable heading IDs, and a table of contents from the generated navigation manifest."
-group: docs-site
----
-
-# Render MDX and TOC
-
-Leadtype does not render your website. Your docs app owns MDX runtime components, layout, accessibility, and the "On this page" UI. Leadtype defines the contracts that keep the rendered HTML and generated markdown aligned.
-
-## Register MDX components
-
-Use the component names Leadtype's remark stack knows how to flatten:
-
-```tsx
-import { mdxComponents } from "@/components/docs-mdx";
-
-export const components = {
- ...mdxComponents,
-};
-```
-
-The naming contract is documented in [Components](/docs/authoring/components). If your app uses different component names, add a custom remark plugin that maps them back before Leadtype flattens MDX to markdown.
-
-## Use the same heading slugs
-
-`resolveDocsNavigation` extracts a table of contents from page headings. Your rendered headings need matching `id` attributes or sidebar links will miss.
-
-Import `slugifyDocsHeading` from the fs-free readability entry point:
-
-```tsx
-import { slugifyDocsHeading } from "leadtype/llm/readability";
-import { type ComponentPropsWithoutRef, isValidElement } from "react";
-
-type HeadingProps = ComponentPropsWithoutRef<"h1">;
-
-function textFromChildren(children: unknown): string {
- if (typeof children === "string" || typeof children === "number") {
- return String(children);
- }
- if (Array.isArray(children)) {
- return children.map(textFromChildren).join("");
- }
- if (isValidElement(children)) {
- const elementProps = children.props as { children?: unknown };
- return textFromChildren(elementProps.children);
- }
- return "";
-}
-
-function createHeading(level: 1 | 2 | 3 | 4 | 5 | 6) {
- return ({ children, id, ...props }: HeadingProps) => {
- const Component = `h${level}` as const;
- const headingId = id ?? slugifyDocsHeading(textFromChildren(children));
- return (
-
- {children}
-
- );
- };
-}
-```
-
-Authors can still pin an anchor by passing an explicit `id`.
-
-## Generate navigation with TOC data
-
-`resolveDocsNavigation` includes `toc` on every page. The default range is `h2` to `h3`.
-
-```ts
-import { resolveDocsNavigation } from "leadtype/llm";
-import docsConfig from "../docs/docs.config";
-
-const navigation = await resolveDocsNavigation({
- srcDir: ".",
- baseUrl: "https://example.com",
- groups: docsConfig.groups,
- toc: { minLevel: 2, maxLevel: 4 },
-});
-```
-
-Write the navigation object to a generated JSON file and import it from your sidebar.
-
-## Render the sidebar
-
-Look up the current page in the manifest and pass `currentPage.toc` to your sidebar component. The example app includes a complete React implementation with scroll-spy, hash sync, active highlighting, and sticky positioning:
-
-[`apps/example/src/components/table-of-contents.tsx`](https://github.com/inthhq/leadtype/blob/main/apps/example/src/components/table-of-contents.tsx)
-
-## Troubleshooting
-
-- **TOC links do not scroll anywhere.** Your heading IDs do not match the extracted slugs. Use `slugifyDocsHeading` in the rendered heading components.
-- **A page TOC is empty.** All headings are outside the configured `minLevel` and `maxLevel` range. Defaults exclude `h1` and headings deeper than `h3`.
-- **Sidebar order differs from llms.txt.** The app is not using the same `docs.config.ts` groups as the generation step.
diff --git a/docs/build/use-the-source-primitive.mdx b/docs/build/use-the-source-primitive.mdx
new file mode 100644
index 0000000..707310f
--- /dev/null
+++ b/docs/build/use-the-source-primitive.mdx
@@ -0,0 +1,238 @@
+---
+title: "Use the source primitive"
+description: "Wire createDocsSource into Next, Astro, Vite, Nuxt, SvelteKit, or any MDX-aware bundler. Same primitive, multiple host shapes."
+group: docs-site
+order: 20
+---
+
+# 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`](/docs/build/integrate-with-fumadocs) — it's a thinner wrapper around this same primitive.
+
+## TL;DR
+
+The primitive itself is identical across frameworks:
+
+```ts title="lib/source.ts"
+import { createDocsSource } from "leadtype";
+
+export const source = await createDocsSource({
+ contentDir: "./content/docs",
+ baseUrl: "https://example.com",
+});
+```
+
+Wire `mdxSourcePlugins` 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
+
+```sh
+bun add leadtype
+```
+
+Plus an MDX integration for your bundler (`@next/mdx`, `@astrojs/mdx`, `@mdx-js/rollup`, etc.).
+
+## Wire into your framework
+
+`mdxSourcePlugins` expands `` partials and resolves `` at build time, while leaving every custom tag (``, ``, ``, …) as JSX for your runtime components.
+
+### Next App Router
+
+```ts title="next.config.mjs"
+import createMDX from "@next/mdx";
+import { mdxSourcePlugins } from "leadtype/mdx";
+
+export default createMDX({
+ options: { remarkPlugins: [...mdxSourcePlugins] },
+})({ pageExtensions: ["ts", "tsx", "mdx"] });
+```
+
+```tsx title="app/docs/[[...slug]]/page.tsx"
+import { notFound } from "next/navigation";
+import { MDXRemote } from "next-mdx-remote-client/rsc";
+import { source } from "@/lib/source";
+import { mdxComponents } from "@/lib/mdx-components";
+
+export default async function DocsPage({
+ params,
+}: { params: Promise<{ slug?: string[] }> }) {
+ const { slug = [] } = await params;
+ const page = await source.loadPage(slug);
+ if (!page) notFound();
+
+ return (
+
+
{page.title}
+ {page.description ?
{page.description}
: null}
+
+
+ );
+}
+
+export async function generateStaticParams() {
+ const pages = await source.listPages();
+ return pages.map((page) => ({ slug: page.slug }));
+}
+```
+
+### Astro Content Collections
+
+```ts title="astro.config.mjs"
+import { defineConfig } from "astro/config";
+import mdx from "@astrojs/mdx";
+import { mdxSourcePlugins } from "leadtype/mdx";
+
+export default defineConfig({
+ integrations: [mdx({ remarkPlugins: [...mdxSourcePlugins] })],
+});
+```
+
+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](https://docs.astro.build/en/guides/content-collections/) for the routing pattern.
+
+### Vite + `@mdx-js/rollup` (works for Vue, Solid, Svelte starters)
+
+```ts title="vite.config.ts"
+import mdx from "@mdx-js/rollup";
+import { mdxSourcePlugins } from "leadtype/mdx";
+
+export default {
+ plugins: [
+ mdx({ remarkPlugins: [...mdxSourcePlugins] }),
+ // ...your framework plugin: viteReact / vue / solid / svelte
+ ],
+};
+```
+
+### Nuxt
+
+```ts title="nuxt.config.ts"
+import { mdxSourcePlugins } from "leadtype/mdx";
+
+export default defineNuxtConfig({
+ modules: ["@nuxtjs/mdc"],
+ mdc: { remarkPlugins: { ...mdxSourcePlugins } },
+});
+```
+
+### SvelteKit + `mdsvex`
+
+```ts title="svelte.config.js"
+import { mdsvex } from "mdsvex";
+import { mdxSourcePlugins } from "leadtype/mdx";
+
+export default {
+ extensions: [".svelte", ".svx", ".mdx"],
+ preprocess: mdsvex({ remarkPlugins: [...mdxSourcePlugins] }),
+};
+```
+
+### Pattern for any other host
+
+If your framework's MDX integration accepts a remark plugin list, leadtype works. Three pieces every time:
+
+1. Add `mdxSourcePlugins` to the remark list so `` and `` resolve at build time.
+2. Implement components against the [tag types from `leadtype/mdx`](/docs/reference/mdx).
+3. 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:
+
+```tsx title="lib/mdx-components.tsx"
+import type { CalloutProps, TabsProps, StepProps } from "leadtype/mdx";
+
+export const mdxComponents = {
+ Callout: ({ variant, title, children }: CalloutProps & { children?: React.ReactNode }) => (
+
+ ),
+ // ... Tabs, Tab, Steps, Step, Cards, Card, TypeTable, etc.
+};
+```
+
+The full tag inventory and intersection patterns for React, Vue, Svelte, Solid, and Astro live in [`leadtype/mdx`](/docs/reference/mdx).
+
+## Build the sidebar from navigation
+
+```tsx title="components/sidebar.tsx"
+import { source } from "@/lib/source";
+
+export async function Sidebar({ currentUrlPath }: { currentUrlPath: string }) {
+ const navigation = await source.getNavigation();
+ return (
+
+ );
+}
+```
+
+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:
+
+```tsx
+import { slugifyDocsHeading } from "leadtype/llm/readability";
+
+function textFromChildren(children: unknown): string {
+ if (typeof children === "string" || typeof children === "number") {
+ return String(children);
+ }
+ if (Array.isArray(children)) return children.map(textFromChildren).join("");
+ // (recurse into React elements as needed)
+ return "";
+}
+
+const Heading2 = ({ children, id, ...props }: React.HTMLAttributes) => {
+ const headingId = id ?? slugifyDocsHeading(textFromChildren(children));
+ return
{children}
;
+};
+```
+
+Wire `Heading2` (and `h3`, etc.) into your `mdxComponents` map. Authors can still pin an explicit `id` on a heading.
+
+## Build a search index
+
+```tsx title="app/api/search/route.ts"
+import { source } from "@/lib/source";
+
+const bundle = await source.buildSearchIndex();
+
+export async function GET() {
+ return Response.json(bundle.index);
+}
+```
+
+For provider-specific search (Vercel AI, TanStack, Cloudflare), feed the bundle into a `leadtype/search/*` adapter — see [Add search](/docs/build/add-search).
+
+## Troubleshooting
+
+- **`` tags survive into the rendered output.** You forgot to add `mdxSourcePlugins` to your MDX compiler's remark plugin list.
+- **`` renders unresolved.** The source preset converts these to `` only when `extractTypeFromFile` succeeds. Make sure `typescript` is installed in the docs app and `basePath` resolves to the project that contains the type.
+- **TOC links don't scroll.** Rendered heading IDs don't match. Wire `slugifyDocsHeading` into your heading components.
+- **Sidebar order doesn't match `llms.txt`.** Your app and the CLI are loading different `docs.config.ts` files. Centralize the config and import it in both.
+
+## Reference
+
+- [`leadtype/mdx`](/docs/reference/mdx) — tag types, `mdxSourcePlugins`, include helpers
+- [`createDocsSource`](/docs/reference/source) — full API surface for the primitive
+- [`leadtype/fumadocs`](/docs/build/integrate-with-fumadocs) — fumadocs adapter recipe
diff --git a/docs/build/validate-in-ci.mdx b/docs/build/validate-in-ci.mdx
index e5822a1..213772d 100644
--- a/docs/build/validate-in-ci.mdx
+++ b/docs/build/validate-in-ci.mdx
@@ -2,6 +2,7 @@
title: "Validate in CI"
description: "Run leadtype lint in CI so frontmatter, navigation, and link issues fail PRs before publish."
group: docs-site
+order: 70
---
# Validate in CI
diff --git a/docs/docs.config.ts b/docs/docs.config.ts
index f1fc592..9a3c826 100644
--- a/docs/docs.config.ts
+++ b/docs/docs.config.ts
@@ -15,7 +15,8 @@ export default defineDocsConfig({
{ urlPath: "/docs" },
{ urlPath: "/docs/quickstart" },
{ urlPath: "/docs/how-it-works" },
- { urlPath: "/docs/build/connect-docs-site" },
+ { urlPath: "/docs/build/build-a-docs-site" },
+ { urlPath: "/docs/build/use-the-source-primitive" },
{ urlPath: "/docs/build/add-search" },
{ urlPath: "/docs/build/optimize-docs-for-agents" },
{ urlPath: "/docs/package-docs/bundle" },
diff --git a/docs/index.mdx b/docs/index.mdx
index 47b8a08..ce36574 100644
--- a/docs/index.mdx
+++ b/docs/index.mdx
@@ -29,44 +29,34 @@ It is not a docs website framework. Bring your own UI — Next.js, TanStack Star
site_out --> search
bundle_out --> offline_agents`} />
-## Choose your path
+## Start here
-Pick the job that matches what you are building. Each path starts with the minimum setup, then links to the lower-level API reference only when you need it.
+**[Quickstart →](/docs/quickstart)** — three steps to a working source primitive, then plug it into your framework.
+
+Or skip ahead: [Build a docs site](/docs/build/build-a-docs-site) compares every integration path side-by-side.
+
+## What leadtype produces
-## What you get
-
-
-
- Author MDX with familiar components — `Callout`, `Tabs`, `Steps`, `Mermaid`, `TypeTable`, and others. Add `group:` in frontmatter to place pages in the navigation tree.
-
-
- For a website: converts MDX to markdown, builds `llms.txt` plus root `llms-full.txt`, generates a search index, writes Agent Readability discovery files, and resolves navigation. With `--bundle`: emits `AGENTS.md` plus per-topic `.md` files with relative links that still work after npm install.
-
-
- Humans get HTML from your app. HTTP agents get markdown via content negotiation or `/llms.txt`. Package consumers can point their root `AGENTS.md` or README at `node_modules//AGENTS.md` for version-matched offline docs.
-
-
-
## Next
-- New here? Read the **[Quickstart](/docs/quickstart)** — five minutes to generated output.
+- New here? Read the **[Quickstart](/docs/quickstart)** — three steps to a working source.
- Want the mental model first? Read **[How it works](/docs/how-it-works)** for the pipeline diagram and the names of every artifact it produces.
- Comparing tools? See **[Methodology](/docs/methodology)** for how leadtype differs from Fumadocs, Starlight, and Mintlify.
diff --git a/docs/methodology.mdx b/docs/methodology.mdx
index e714a61..c09b1f3 100644
--- a/docs/methodology.mdx
+++ b/docs/methodology.mdx
@@ -21,17 +21,21 @@ Choose a website framework when the main job is publishing a polished docs UI qu
## What leadtype owns
-- MDX-to-markdown conversion via a remark plugin stack.
-- `llms.txt`, markdown mirrors, and root `llms-full.txt` fallback context for agents.
-- A static, edge-safe search index plus optional source-grounded answer streaming.
-- Lint rules for frontmatter, navigation metadata, and internal links.
-- CLI orchestration so the whole pipeline runs from one command.
+- The **MDX tag contract** — typed prop shapes for ``, ``, ``, ``, and the rest of the custom tags (see [`leadtype/mdx`](/docs/reference/mdx)).
+- A **build-time source preset** that expands `` partials, resolves ``, and strips authoring `import`s — without flattening live components.
+- A **framework-neutral source primitive** (`createDocsSource`) exposing navigation, page loading, search index building, and include resolution.
+- A thin **fumadocs adapter** (`leadtype/fumadocs`) wiring the source into fumadocs's `Source` interface.
+- The agent / LLM pipeline: MDX-to-markdown conversion, `llms.txt`, root `llms-full.txt` fallback context, markdown mirrors, sitemap, and AGENTS.md bundles.
+- A static, edge-safe **search index** plus optional source-grounded answer streaming.
+- **Lint rules** for frontmatter, navigation metadata, and internal links.
+- **CLI orchestration** so the whole pipeline runs from one command.
## What leadtype does not own
- Visual UI, theming, or component styling.
+- Runtime component implementations — your docs app implements components against the tag contract (see [Components](/docs/authoring/components) and [`leadtype/mdx`](/docs/reference/mdx)).
- Routing, hosting, deployment, or analytics.
-- A prebuilt MDX component library — your docs app provides those (see [Components](/docs/authoring/components)).
+- The MDX compiler — leadtype produces the source preset; your bundler (Next App Router, Vite, fumadocs-mdx, Astro) does the compile.
## When the combination shines
diff --git a/docs/package-docs/bundle.mdx b/docs/package-docs/bundle.mdx
index ff43efc..f5dd9bc 100644
--- a/docs/package-docs/bundle.mdx
+++ b/docs/package-docs/bundle.mdx
@@ -31,7 +31,7 @@ The website is for humans and HTTP agents. The package-bundled docs are for codi
[`AGENTS.md`](https://agents.md) is the **filesystem convention** that solves this. Tools like Claude Code, OpenAI Codex, Cursor, GitHub Copilot, Aider, Devin, and others can read `AGENTS.md` when working with files on disk. An `AGENTS.md` inside `node_modules//` is the right shape for version-matched package docs: relative links work, no network is required, and the content matches the installed version.
-leadtype emits both — `llms.txt` in [website mode](/docs/build/connect-docs-site) for HTTP-discoverable agents, and `AGENTS.md` in `--bundle` mode for offline filesystem-discoverable agents.
+leadtype emits both — `llms.txt` in [website mode](/docs/build/build-a-docs-site) for HTTP-discoverable agents, and `AGENTS.md` in `--bundle` mode for offline filesystem-discoverable agents.
## Generate into the package
@@ -93,8 +93,7 @@ Add `AGENTS.md` and `docs` to `files` and run generation as a build or prepack s
If you need full control over plugin order or custom validation, run the library APIs directly from a script:
-```ts
-// scripts/generate-docs.ts
+```ts title="scripts/generate-docs.ts"
import { rm } from "node:fs/promises";
import { convertAllMdx } from "leadtype/convert";
import { generateAgentsMd, resolveDocsNavigation } from "leadtype/llm";
@@ -169,7 +168,7 @@ This is the same pattern Next.js uses to point agents at `node_modules/next/dist
Use this when **agents should understand the package from the installed dependency itself** — coding agents that don't have web access, IDE assistants, CLI tools, or air-gapped environments.
-Don't use this if your only goal is a public docs website. For that, see [Connect a docs site](/docs/build/connect-docs-site). You can use both — they read the same source MDX, just emit different shapes.
+Don't use this if your only goal is a public docs website. For that, see [Build a docs site](/docs/build/build-a-docs-site). You can use both — they read the same source MDX, just emit different shapes.
## What's next
diff --git a/docs/quickstart.mdx b/docs/quickstart.mdx
index 508c908..b31e458 100644
--- a/docs/quickstart.mdx
+++ b/docs/quickstart.mdx
@@ -1,28 +1,23 @@
---
title: "Quickstart"
-description: "Install leadtype, run the hosted-docs pipeline once, and inspect the generated artifacts."
+description: "Install leadtype, author your first MDX page, and create a source. Then plug it into whatever framework you're using."
group: get-started
---
# Quickstart
-Five minutes from a folder of MDX to generated docs artifacts.
+Three steps to a working source primitive. Then plug it into your framework — Next, Fumadocs, Astro, Vite + Vue/Solid/Svelte, Nuxt, SvelteKit — using one of the recipes below.
## Install
-`leadtype` ships a CLI plus focused library entry points. Start with the CLI; use the APIs only when your build needs custom plugin order, filtering, or output paths.
-
## Author one page
-Create `docs/index.mdx` in your repo:
-
-```mdx
+```mdx title="content/docs/index.mdx"
---
title: "My library"
description: "What it does in one sentence."
-group: get-started
---
# My library
@@ -32,67 +27,79 @@ Welcome.
Every page needs a `title`. Add `group:` when the page should appear in generated navigation and `llms.txt` sections. See [Frontmatter](/docs/authoring/frontmatter) for the full content contract.
-## Generate hosted docs output
+## Create the source
-```bash
-npx leadtype generate \
- --src . \
- --out public \
- --base-url https://example.com
-```
-
-That command reads `docs/*.mdx`, converts it to markdown, resolves groups, builds search JSON, and writes hosted agent artifacts.
+```ts title="lib/source.ts"
+import { createDocsSource } from "leadtype";
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+export const source = await createDocsSource({
+ contentDir: "./content/docs",
+ baseUrl: "https://example.com",
+});
+```
-Open `public/docs/index.md` first. It shows what your MDX becomes after the remark component flattening pipeline runs. Then open `public/llms.txt` to see the hosted routing file that HTTP agents start from.
+That's the framework-neutral primitive. You can now call:
-
- `apps/example/` in the [leadtype repo](https://github.com/inthhq/leadtype) is the production docs site for these docs. It runs the same pipeline you just ran, on TanStack Start, with markdown content negotiation, sitemap regeneration, and JSON-LD wired up. Clone it when you want a copy-pastable end-to-end setup.
-
+- `source.loadPage(slug)` — resolved markdown + AST + frontmatter + TOC
+- `source.listPages()` — every page's slug, urlPath, and metadata
+- `source.getNavigation()` — grouped sidebar tree
+- `source.buildSearchIndex()` — static search bundle
+- `source.resolveInclude(specifier)` — standalone include resolver
-## Choose the next setup step
+## Plug it into your framework
-| Goal | Next page |
-| --- | --- |
-| Wire the generator into an app build | [Connect a docs site](/docs/build/connect-docs-site) |
-| Render HTML pages and an "On this page" sidebar | [Render MDX and TOC](/docs/build/render-mdx-and-toc) |
-| Serve markdown, sitemaps, robots, and JSON-LD for agents | [Optimize docs for agents](/docs/build/optimize-docs-for-agents) |
-| Query the generated static search index | [Add search](/docs/build/add-search) |
-| Publish AGENTS.md inside an npm package | [Bundle docs into a package](/docs/package-docs/bundle) |
+Pick the recipe that matches your stack. Each one shows the wiring on top of the same `createDocsSource()` you just set up.
+
+
+
+## Or: write static artifacts to disk
+
+Some pipelines need flat files — CDN-only deploys, static exports, agent-only services, multiple sibling apps sharing one corpus. Use the CLI:
+
+```sh
+npx leadtype generate --src . --out public --base-url https://example.com
+```
+
+That writes `llms.txt`, `llms-full.txt`, `docs/*.md`, search index, sitemap, and `agent-readability.json` to disk. See [Generate static artifacts](/docs/build/generate-static-artifacts) for the full flow.
+
+## Next steps
+
+| Goal | Page |
+| --- | --- |
+| Compare every integration shape side-by-side | [Build a docs site](/docs/build/build-a-docs-site) |
+| Implement custom MDX tags (Callout, Tabs, Steps, …) | [`leadtype/mdx`](/docs/reference/mdx) |
+| Add search | [Add search](/docs/build/add-search) |
+| Validate frontmatter and links in CI | [Validate in CI](/docs/build/validate-in-ci) |
+| Serve markdown, sitemaps, robots, and JSON-LD for agents | [Optimize docs for agents](/docs/build/optimize-docs-for-agents) |
+| Publish AGENTS.md inside an npm package | [Bundle docs into a package](/docs/package-docs/bundle) |
diff --git a/docs/reference/evals.mdx b/docs/reference/evals.mdx
index 42b5ff8..3f3f277 100644
--- a/docs/reference/evals.mdx
+++ b/docs/reference/evals.mdx
@@ -16,7 +16,7 @@ Leadtype treats agent-facing docs as behavior, not just files on disk. The repo
| Hosted docs | `llms.txt` + markdown mirrors + `llms-full.txt` variants | Simulates a hosted docs web root as local files. Agents start at `/llms.txt`, then choose page-level markdown, root `llms-full.txt`, or experimental grouped/router formats depending on the variant under test. |
The hosted-docs benchmark uses the same nine-page corpus for every variant:
-quickstart, how-it-works, frontmatter, components, connect-docs-site,
+quickstart, how-it-works, frontmatter, components, build-a-docs-site,
package-docs bundle, CLI, LLM bundles, and Search. Those pages are split across
five groups: Get Started, Authoring, Build, Ship Package Docs, and Reference.
diff --git a/docs/reference/llm.mdx b/docs/reference/llm.mdx
index 0b46312..3e7e2a7 100644
--- a/docs/reference/llm.mdx
+++ b/docs/reference/llm.mdx
@@ -452,7 +452,7 @@ Now your sidebar can import a static manifest with the same group tree the LLM f
## Tables of contents
-For the heading slug contract and renderer wiring, see [Render MDX and TOC](/docs/build/render-mdx-and-toc). This section covers the build-time APIs only.
+For the heading slug contract and renderer wiring, see [Use the source primitive](/docs/build/use-the-source-primitive). This section covers the build-time APIs only.
`resolveDocsNavigation` includes a `toc` array on every page by default. The default range is `h2`–`h3`, which keeps page-level `h1` titles out of sidebars.
diff --git a/docs/reference/mdx.mdx b/docs/reference/mdx.mdx
new file mode 100644
index 0000000..75d00b8
--- /dev/null
+++ b/docs/reference/mdx.mdx
@@ -0,0 +1,257 @@
+---
+title: "leadtype/mdx"
+description: "Tag type contracts and the build-time source preset for consumers rendering MDX themselves."
+group: reference
+---
+
+# `leadtype/mdx`
+
+The `leadtype/mdx` subpath is the **consumer-facing MDX surface** — everything you need to compile leadtype-authored MDX in your own renderer (fumadocs, Next App Router, Vite + @mdx-js, Astro content collections).
+
+It exports three things:
+
+1. **Tag type contracts** — typed prop shapes for every custom MDX tag.
+2. **`mdxSourcePlugins`** — a remark preset that performs build-time resolution only (expand includes, resolve ``, strip authoring `import`s) and leaves every other custom tag as JSX.
+3. **Include-resolution helpers** — `resolveInclude`, `parseIncludeSpecifier`, `extractMdxSection` for direct use.
+
+Pair it with `leadtype/remark` (markdown flattening for the agent/LLM pipeline) — they are sibling surfaces, not alternatives. Most projects use both.
+
+## The MDX-source preset
+
+```ts
+import createMDX from "@next/mdx";
+import { mdxSourcePlugins } from "leadtype/mdx";
+
+const withMDX = createMDX({
+ options: {
+ remarkPlugins: [...mdxSourcePlugins],
+ },
+});
+```
+
+The preset is intentionally minimal — only the transforms that **must** run at build time:
+
+| Plugin | Purpose |
+| --- | --- |
+| `remarkInclude` | Expands ``, ``, `` |
+| `remarkResolveTypeTableJsx` | `` → `` |
+| `remarkResolveDocPlaceholders` | Resolves `{{...}}` placeholders against doc context |
+| `remarkRemoveImports` | Strips authoring `import` statements that aren't needed at runtime |
+
+Every other custom tag (``, ``, ``, ``, …) stays JSX so your runtime components render them.
+
+## Framework-neutral by design
+
+Tag types describe the **author surface** — the attributes that appear on a tag in source MDX. They deliberately do **not** import from any UI framework: `children` is typed as `unknown` so you can intersect with your framework's native child type.
+
+The same shape works in React, Vue, Svelte, Solid, Astro, Qwik, or anything else with an MDX compiler that accepts remark plugins.
+
+### React
+
+```tsx
+import type { CalloutProps } from "leadtype/mdx";
+import type { HTMLAttributes, ReactNode } from "react";
+
+type ReactCalloutProps = Omit &
+ HTMLAttributes & { children?: ReactNode };
+
+export function Callout({ variant, title, children, ...rest }: ReactCalloutProps) {
+ return (
+
+ );
+}
+```
+
+### Vue
+
+```vue
+
+
+
+
+
+```
+
+### Svelte
+
+```svelte
+
+
+
+```
+
+### Solid
+
+```tsx
+import type { CalloutProps } from "leadtype/mdx";
+import type { JSX } from "solid-js";
+
+type SolidCalloutProps = Omit & {
+ children?: JSX.Element;
+};
+
+export function Callout(props: SolidCalloutProps) {
+ return (
+
+ );
+}
+```
+
+### Astro
+
+```astro
+---
+import type { CalloutProps } from "leadtype/mdx";
+type Props = Omit;
+const { variant = "info", title } = Astro.props as Props;
+---
+
+
+```
+
+### Full type inventory
+
+```ts
+import type {
+ // Layout
+ AudienceProps,
+ AudienceTarget,
+ SectionProps,
+ DetailsProps,
+
+ // Callouts
+ CalloutProps,
+ CalloutVariant,
+ CalloutTypeAlias,
+
+ // Navigation / structure
+ TabsProps,
+ TabProps,
+ StepsProps,
+ StepProps,
+ AccordionProps,
+ AccordionItemProps,
+
+ // Cards / topics
+ CardsProps,
+ CardProps,
+ CardVariant,
+ TopicSwitcherProps,
+ TopicSwitcherItem,
+
+ // File tree
+ FileTreeProps,
+ FolderProps,
+ FileProps,
+
+ // Code / commands
+ CommandTabsProps,
+ CommandMode,
+ PackageManager,
+ ExampleProps,
+ ExampleSourceFile,
+ PromptProps,
+
+ // Type tables
+ TypeTableProps,
+ TypeTableProperty,
+ ExtractedTypeTableProps,
+
+ // Diagrams
+ MermaidProps,
+} from "leadtype/mdx";
+```
+
+Every prop name is part of the 1.0 contract — bumping a shape is a breaking change. New optional props are minor.
+
+### Build-time only: ``
+
+`` is an authoring convenience. The source preset replaces it at build time with ``, so consumers only implement the runtime `` component:
+
+```ts
+import type { TypeTableProps } from "leadtype/mdx";
+
+export function TypeTable({ properties, title, description }: TypeTableProps) {
+ return (
+
+ {title ?