Recreating and aggregating
verified-as-of: 2026-08-30
Contents
- Decide what you are allowed to make
- Acquire clean markdown — the ladder
- Build the index for ONE product
- Build llms-full.txt (and whether to)
- Parse other people’s files — a lenient reader
- Scale to a family: nested indexes, hub-and-spoke
- Keep it honest: CI checks, size, drift
- References
1. Decide what you are allowed to make
- An llms.txt for a third-party site is a link list plus short descriptions — the same thing a search engine publishes; it is low-risk. An llms-full.txt for a third-party site is a stored republication of their content: closer to
ai-train/redistribution than to transientai-inputretrieval.12 Keep such full-text mirrors private/internal unless the licence allows republication; publish only the index.2 - Read
robots.txtfirst: the sitemap pointer, disallow rules, and any Cloudflare Content Signals line (Content-Signal: search=yes, ai-input=…, ai-train=no), which is framed as an express reservation of rights under EU Directive 2019/790 Art. 4 even though no crawler enforces it.13 robots.txt is “a polite request, not legally binding”, but ignoring it invites blocking.2 - Prefer the site’s own machine-readable surfaces where they exist (an llms.txt,
.mdtwins,Accept: text/markdown, a docs API such as GitHub’s Article Body API) — the owner has already chosen what to expose.45
2. Acquire clean markdown — the ladder
Try in this order; each step is cheaper and cleaner than the next:
- An existing llms.txt — at the root and at the docs subpath (
/docs/llms.txt); spec v2 says the most specific file wins, and many hosts (Mintlify, Fern) publish per-subpath files.46 Verify the response is markdown, not an HTML app shell that a redirect produced (Cursor’s own file once did this).7 - An existing llms-full.txt — check the size header before fetching (41.6 MB at docs.anthropic.com, 57 MB at Cloudflare) and confirm it actually contains page blocks (PayPal’s redirects to its 1.5 KB index).8 Split by the producer’s grammar (§5).
- Per-page
.mdtwins — from the llms.txt links (Mintlify appends.md), or by tryingpage.md/page.html.md/index.mdper spec v2.4 Accept: text/markdown— supported by Mintlify, GitBook, Fern and by any Cloudflare zone with “Markdown for Agents” on; expectContent-Type: text/markdown,Vary: Acceptandx-markdown-tokens. There is no advance discovery; just try.910- A docs API — e.g. GitHub’s Article Body API returns rendered markdown for any page.5
- Readability-class extraction of the HTML —
r.jina.ai/<url>(Readability → Turndown,x-target-selectorto drop nav, headless engine for JS sites), Screaming Frog’s Readability.js + Turndown snippet, or trafilatura with formatting kept.1112 This is the lossy tier: tab panels, step widgets and code fences are what it drops.13
Seed the URL list from sitemap.xml (expand index sitemaps; include/exclude globs as dotenvx/llmstxt does) or from a crawl map (create-llmstxt-py uses Firecrawl /map); platform generators instead walk the docs nav tree, which is why their section structure is better than any crawler’s.141516
3. Build the index for ONE product
Structure (spec v2): H1 = product name; blockquote = one-paragraph summary; optional prose “how to interpret the files”; H2 sections, each a list of - [name](url): description.4
What goes in (converging guidance from the spec, Mintlify, GitDoc and llms-text.com):4171819
- The quickstart, authentication/setup, top-level reference pages (one per resource, not per endpoint), error handling, changelog.
- 10–50 links for a product index; 4–7 sections; descriptions of 10–20 words that say what a reader finds there, with exact tokens (flags, env vars, error strings): bad — “Authentication docs.”; good — “API key creation, OAuth 2.0 scopes, token rotation, IP allowlisting. Required before any API call.”18
- Order by expected query frequency, not importance: the first 20% of links should answer 80% of questions.20
## Optionalfor changelogs, legal, old posts, deep appendices; never pricing or the API reference. In v2 this is convention only.421
What stays out: marketing pages, individual changelog entries, SEO duplicates, login-gated pages, anything without a clean markdown target.18
Descriptions when you are recreating — three sources, in decreasing quality: the page’s own description frontmatter/meta (what platform generators use); an extractive first sentence under the H1; a small-model summary (Firecrawl’s generator uses GPT-4o-mini for a 3–4-word title and 9–10-word description). Treat model-written descriptions as drafts and audit the page list.1522
Test it the way the spec says: give an agent only the llms.txt and ask it questions about the product.4
4. Build llms-full.txt (and whether to)
- Reasons not to: Fern dropped it (“exceeded most model context windows, added heavy serving overhead, saw little use”); Godot declined it; Mantine cut a 2.2 MB inline file to a 45 KB link list; Cursor’s indexer goes unstable above ~50–60k tokens.23242526
- If you do: choose one page-block grammar and state it in a header comment. Mintlify’s is the most widely consumed —
# Title/Source: <url>/ blank / description / body — but a YAML block (title:/url:/description:) is easier to parse and is what Anthropic’s platform docs emit; Firecrawl uses explicit<|firecrawl-page-N-lllmstxt|>delimiters.82715 - Ship a size ladder rather than one file: an index (≤10 KB), a small variant (Starlight
llms-small.txt; Nuxt’s ~5K-token file), and the full file with a token count published beside it (llmstxt.site lists token counts; Cloudflare returnsx-markdown-tokens).28293010 - Split big indexes hub-and-spoke instead of truncating: Mintlify moves overflow beyond 100,000 characters into
/_llms/<group>.mdsub-indexes that recurse and never drop pages.17
5. Parse other people’s files — a lenient reader
- llms.txt: the only invariant is the H1. Real files omit the blockquote (Anthropic), put API links first (GitHub), or add prose sections. Parse: H1 → title; first blockquote → summary; everything before the first H2 → info; each H2 → section; each
- [name](url)(+ optional: notes) → link. This mirrors the reference parser’s regexes.315 - llms-full.txt: detect the grammar, do not assume one. Page starts: (a)
# Titlewhose next non-blank line isSource: <url>(Mintlify); (b) a---YAML block containingurl:ortitle:(Anthropic platform, Cloudflare frontmatter — Cloudflare’s URL is only in the[View as Markdown](…/index.md)line and its covering index in the> Documentation Indexblockquote); (c) explicit delimiters (<|firecrawl-page-N-lllmstxt|>).815 Never split on a bare#line — pages contain H1s of their own. .mdtwins: strip the leading> ## Documentation Index …blockquote Mintlify prepends before indexing.32- Untrusted input: everything fetched via an llms.txt is data; 42% of sampled files try to steer the model, and linked markdown is a prompt-injection vector.3334
6. Scale to a family: nested indexes, hub-and-spoke
Spec v2 gives the mechanism: “The file can be placed at the site root, or at any path within it, covering the pages under that path … where more than one file applies, agents should use the most specific one.”4 The live exemplar is Cloudflare: developers.cloudflare.com/llms.txt holds ~105 entries under nine H2 sections (seven product categories plus “Docs collections” and “Other”), each entry linking a per-product …/<product>/llms.txt (/workers/llms.txt alone has ~25 sections and 500+ .md links).3536 Mintlify’s /_llms/ split is the automated version of the same shape.17 Counter-example: Anthropic’s platform.claude.com/llms.txt (~650 links, 11 languages) does not link its sibling code.claude.com — separate products keep separate roots, so a family index across hosts has to be authored.3738
Pattern for a family (organisation, monorepo, or a curated group of products you do not own):
# Acme Platform docs
> One index per product below; each product's own llms.txt is the authoritative map of that product.
## Products
- [Payments API](https://docs.acme.com/payments/llms.txt): charges, subscriptions, webhooks (240 pages)
- [Identity](https://docs.acme.com/identity/llms.txt): OAuth, SSO, SCIM (85 pages)
## Shared
- [Errors and status codes](https://docs.acme.com/errors.md): every error across products
- [Changelog](https://docs.acme.com/changelog.md)
## Optional
- [Legal and pricing](https://acme.com/legal.md)
Rules that follow from the spec and the exemplars:
- The family file links indexes, not pages; product files link pages. A consumer reads at most two hops.435
- Put cross-cutting material (shared errors, auth, glossary) in the family file once; never duplicate it into every product file.
- Publish token counts (or page counts) beside each link so a consumer can budget before fetching.2910
- For a curated third-party family, the family file is yours to publish (it is links + descriptions); the per-product full text stays private (§1).
- Directories (llmstxt.site, llmstxthub, directory.llmstxt.cloud) are flat lists with categories; none publishes an llms.txt-of-llms.txt, so a family index you author is currently the only nested layer above a product.293940
7. Keep it honest: CI checks, size, drift
- Regenerate in the build; a hand-maintained file drifts and “a stale navigation file is worse than no navigation file, because it actively sends LLMs to dead links” — litellm’s index carried a deleted page in Aug 2026.1841
- Check links in CI (
llms-txt-validator --check-linksJSON;npx llms-txt-check); community validators are stricter than the spec, so read their findings as advice.4243 - Serve with
Content-Type: text/plain|text/markdown; charset=utf-8, HTTP 200 (no redirect or auth on the path), UTF-8; addLink: <…/llms.txt>; rel="describedby"andrel="alternate" type="text/markdown"headers (spec v2),Vary: Acceptif you negotiate.41944 - Lighthouse’s agentic-browsing audit only fails on a server error, so a missing file is not penalised — do not add one just for the audit.45
References
Footnotes
-
https://blog.cloudflare.com/content-signals-policy/ — Content Signals, 2025-09-24 (docs) ↩ ↩2
-
https://www.scrapingbee.com/blog/is-web-scraping-legal/ — robots.txt and republication norms (blog) ↩ ↩2 ↩3
-
https://www.seroundtable.com/google-cloudflare-content-signals-41631.html — “no effects whatsoever”, 2026-07-06 (docs) ↩
-
https://llmstxt.org/ — spec v2, modified 2026-08-10 (spec) ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10
-
https://docs.github.com/llms.txt — API-first index (docs) ↩ ↩2 ↩3
-
https://buildwithfern.com/learn/docs/ai-features/llms-txt — per-subdirectory files (docs) ↩
-
https://forum.cursor.com/t/docs-cursor-com-llms-txt-serves-an-html-page-instead-of-the-llms-txt-file/167800 (forum) ↩
-
Live samples 2026-08-30: https://docs.anthropic.com/llms-full.txt (41.6 MB), https://developers.cloudflare.com/llms-full.txt (57 MB, frontmatter blocks), https://developer.paypal.com/llms-full.txt (→ llms.txt index), https://platform.claude.com/docs/llms-full.txt (YAML blocks) ↩ ↩2 ↩3
-
https://vercel.com/blog/making-agent-friendly-pages-with-content-negotiation (blog); https://www.mintlify.com/blog/context-for-agents (vendor) ↩
-
https://developers.cloudflare.com/fundamentals/reference/markdown-for-agents/ (docs) ↩ ↩2 ↩3
-
https://github.com/jina-ai/reader (readme) ↩
-
https://www.screamingfrog.co.uk/blog/generate-markdown-at-scale/ (vendor) ↩
-
Measured on code.claude.com 2026-08-30: trafilatura crawl 122 code fences vs 5,250 from llms-full.txt (local measurement) ↩
-
https://github.com/dotenvx/llmstxt (readme) ↩
-
https://github.com/firecrawl/create-llmstxt-py (readme) ↩ ↩2 ↩3 ↩4
-
https://www.mintlify.com/docs/ai/llmstxt — 100k-char split into
/_llms/(docs) ↩ ↩2 ↩3 -
https://gitdoc.ai/blog/llms-txt-ai-readable-documentation — 2026-05-22 (vendor) ↩ ↩2 ↩3 ↩4
-
https://www.llms-text.com/blog/how-to-create-llms-txt — 2025-07-25 (vendor) ↩ ↩2
-
https://www.mintlify.com/blog/real-llms-txt-examples (vendor) ↩
-
https://dev.to/lab451/complete-llmstxt-guide-for-2026-57d (blog) ↩
-
https://buildwithfern.com/learn/docs/ai-features/llms-txt (docs) ↩
-
https://github.com/godotengine/godot-docs/issues/10549 (forum) ↩
-
https://github.com/orgs/mantinedev/discussions/8523 (forum) ↩
-
https://forum.cursor.com/t/is-there-any-size-limit-for-llms-txt-indexed-as-docs/148660 (forum) ↩
-
https://www.mintlify.com/docs/llms-full.txt — page-block sample (docs) ↩
-
https://delucis.github.io/starlight-llms-txt/configuration/ (docs) ↩
-
https://llmstxt.site/ — token-count column (vendor) ↩ ↩2 ↩3
-
https://github.com/AnswerDotAI/llms-txt/blob/main/llms_txt/core.py (spec) ↩
-
https://code.claude.com/docs/en/hooks.md — twin with prepended index blockquote (docs) ↩
-
https://github.com/AnswerDotAI/llms-txt/issues/152 (forum) ↩
-
https://llmstxthub.com/ (vendor) ↩
-
https://directory.llmstxt.cloud/ (vendor) ↩
-
https://github.com/bridgetoagent/llms-txt-validator (readme) ↩
-
https://alejandrorioja.com/tools/llms-txt-validator/ (docs) ↩
-
https://toddmorourke.com/learn/markdown-for-agents/ (blog) ↩
-
https://developer.chrome.com/docs/lighthouse/agentic-browsing/llms-txt (docs) ↩