Leadtype
Generate & operate

Generate static artifacts

Use 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/.

If you'd rather render docs directly from your bundler, see the source primitive. For source-shape decisions (multi-folder, remote git, pinned refs), see Configure docs sources. For host-specific serving details, see Deploy generated artifacts.

The flow

Rendering diagram...

Fetch the source repo

In 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/.

Lint before generate

Run 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:

Generate

Point --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/.well-known/api-catalog
  • public/docs/*.md
  • public/docs/search-index.json and public/docs/search-content.json
  • public/sitemap.xml, public/sitemap.md, and public/robots.txt
  • public/docs/agent-readability.json
  • configured RSS/Atom feeds, such as public/changelog/rss.xml

For feed-specific configuration and date rules, see Generate RSS and Atom feeds.

Use --json in CI so automation can record resolved groups, output files, filters, and search index stats.

Multi-source mounting

Some projects keep docs and release notes side by side instead of putting everything under docs/:

.docs-src/c15t/
docs/
quickstart.mdx
docs.config.ts
changelog/
v1.mdx

Repeat --docs-dir to include those folders in the same generated corpus:

By default, extra sources are mounted under /docs/<folder>, so changelog/v1.mdx becomes public/docs/changelog/v1.md and /docs/changelog/v1.md.

Use <dir>=<url-prefix> when the folder should keep its own public route:

That still keeps an internal generated copy at public/docs/changelog/v1.md for search and runtime helpers, but it also writes public/changelog/v1.md and emits canonical links such as /changelog/v1 and /changelog/v1.md in llms.txt, search metadata, sitemap entries, and agent-readability.json.

Add feeds in config when that mounted content should publish RSS or Atom:

docs/docs.config.ts

Selected feed pages need stable frontmatter dates. Use explicit date values for changelogs and release notes. For pages where "updated at" should track source edits, default git enrichment writes lastModified when history is available. See Generate RSS and Atom feeds for the full feed contract.

Wire it into the build

Make checkout, lint, and generation run before the framework build:

If the docs source and docs app live in the same repo, skip docs:fetch and point --src at .:

Concurrent invocation

Parallel task graphs often invoke generation more than once at the same time — lint, typecheck, and build each declaring "docs are generated" as a prerequisite. leadtype generate is safe under that pattern:

  • Runs are single-flight per output directory. A cross-process lock (keyed by the resolved --out path, stored under the system temp dir — never inside the output directory) serializes concurrent runs. Later invocations wait for the in-flight run, then regenerate. Abandoned locks recover fast: an interrupted run (Ctrl-C, SIGTERM) releases its lock on the way out, a hard-killed run's lock is reclaimed as soon as its recorded process is gone, and an unidentifiable lock is reclaimed after 10 minutes without refresh. Waiting runs fail loudly after 15 minutes rather than hanging CI (LEADTYPE_LOCK_TIMEOUT_MS overrides this for very large sites).
  • Every artifact is replaced atomically. Files are written to a temp sibling and renamed into place, so a sibling build step reading the output directory (tsc, next build, a dev server watching public/) sees the old artifact or the new one — never a truncated file, and never a missing file for pages that still exist. Temp files leaked by a hard-killed run are swept at the start of the next locked run, so they never linger in a deployed public/.

Set LEADTYPE_NO_LOCK=1 to skip the lock — for example on network filesystems where directory-based locking is unreliable, or when your task runner already serializes generation.

Even though concurrent runs are safe, they are redundant: each waits its turn and regenerates the same output. If your task graph supports it, prefer a single generation task that lint, typecheck, and build all depend on.

Use library APIs for custom pipelines

The CLI is the happy path. Use the library APIs directly when you need custom plugin order, filters, or generated JSON paths. Keep conversion first — LLM files, search, and Agent Readability artifacts read the generated markdown:

Verify

After 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
  • configured feed files such as public/changelog/rss.xml and public/changelog/atom.xml