Redirect renamed pages
Renaming a docs page breaks every link that pointed at it — search results, agent citations, other sites, llms.txt copies agents cached last week. Leadtype's redirect tracking notices renames at generate time, emits a machine-readable redirect map, and refuses to let a page silently disappear.
Enable it
Add a redirects block to docs.config.ts:
On the next leadtype generate, two things appear:
<docs source dir>/paths.lock.json— a lockfile recording every published path with a content hash. Commit this file. It is the record of previously published paths that future runs diff against.<out>/docs/redirects.json— the artifact your app serves redirects from:{ redirects: [{ from, to, status }] }.
Enabling redirects also turns on output pruning (see convertAllMdx prune) — rename detection diffs the emitted page set, so stale mirrors from renamed sources must be garbage-collected or the old path never disappears.
What happens on a rename
Generate compares this run's pages against the lockfile:
-
Pure move (same content, new path): detected automatically by content hash — the body is hashed with frontmatter excluded, so git-enrichment churn doesn't defeat the match. Emits a permanent
308redirect. No authoring needed. -
Move + edit in one commit: the hash no longer matches, so the build fails loudly listing the disappeared paths. Add the old path to the successor page's frontmatter:
-
Intentional deletion: acknowledge it in the config to serve
410 Goneinstead of failing:
Redirects accumulate in the lockfile across generates: when /docs/a moved to /docs/b last month and /docs/b moves to /docs/c today, the old a → b entry collapses to a → c automatically, and entries whose target is later removed degrade to 410.
Ambiguity is never guessed: if two pages with identical content disappear and reappear, the build fails and asks for explicit redirectFrom instead of picking one.
Filtered generates (--include / --exclude) skip redirect tracking and pruning entirely — a partial page set would make every excluded page look deleted. Only full builds touch the lockfile.
Serve the redirects
The generate step emits data; serving is one helper call. For HTML routes, consult the map in your catch-all before rendering a 404:
leadtype/redirects is edge-safe (no Node built-ins), so the resolver runs in Cloudflare Workers and Vercel Edge routes; the generate-time lockfile helpers live under leadtype/redirects/node.
The agent surface is covered for you: pass the entries to createAgentMarkdownResponse and agent-shaped requests for a renamed page — including its .md mirror (/docs/old.md → /docs/new.md) — get the 308/410 directly, while browser requests still fall through to your HTML routing:
Options
| Option | Description |
|---|---|
lockfile | Lockfile path, resolved relative to the docs source directory. Default paths.lock.json. |
removed | Paths acknowledged as intentionally deleted; served as 410 Gone instead of failing the build. |
CI
Because the lockfile is committed, a rename that lands without its lockfile update shows up as a dirty git diff after regeneration — the same "regenerate and assert clean" gate that guards the other generated artifacts covers redirects too.