Format & Spec · October 2026

Root Domain or Docs Subdomain: Where Should llms.txt Live?

Most companies do not have one website — they have a marketing host, a docs host, a status host and a help centre, often on four different subdomains. A single llms.txt at the root covers only the first. We fetched 30 llms.txt URLs on October 24, 2026 — eight brand pairs plus 12 single hosts — to see how the largest sites actually handle it. Nineteen serve a real file, 10 answer 404, and one answers 200 with a 404 page inside the body.

What the 30 Requests Returned

Every request was a normal desktop user agent, redirects followed, and each body parsed for its H1, Markdown links, .md twins and H2 count. Fourteen of the 19 real files arrive as text/plain, five as text/markdown — and all five Markdown responses come from a documentation or help host.

Host Status Type Bytes Links .md
stripe.com200text/plain69,92330624
docs.stripe.com200text/markdown97,577497491
github.com200text/plain28,6581170
docs.github.com200text/markdown28,6421170
www.cloudflare.com200text/plain17,1739082
developers.cloudflare.com200text/plain16,7871120
docs.aws.amazon.com200text/plain418,9481,2991,294
aws.amazon.com404text/html302,410——
help.shopify.com200text/markdown4,71200
shopify.dev404text/html80,728——
docs.python.org404text/html146——
cloud.google.com200text/html41,682——

Of the eight brand pairs, three serve a real file on both hosts (Stripe, GitHub, Cloudflare), two serve only on the documentation side (AWS, Shopify's help centre) and three serve on neither (Microsoft, Mozilla, Python). The pair that publishes only the docs file is the one that proves the point: AWS's 418,948-byte index lives at docs.aws.amazon.com while aws.amazon.com/llms.txt spends 302,410 bytes of HTML saying 404. An agent that starts at the marketing host never learns the docs file exists.

Delegation: The Stripe Pattern

Stripe publishes two different files and the root one points at the other. Its ## Documentation section opens with a single link to the docs host's file, followed by four .md twins:

## Documentation

- [Stripe Documentation](https://docs.stripe.com/llms.txt): Explore our guides and examples to integrate Stripe.
- [API Reference](https://docs.stripe.com/api.md): Complete reference for all Stripe API endpoints.
- [Testing](https://docs.stripe.com/testing.md): Simulate payments and test your integration.

That one line is the whole cross-host strategy. The root file (69,923 bytes, 306 links, H1 # Stripe) describes the marketing site; the docs file (97,577 bytes, 497 links, 491 .md twins, H1 # Stripe Documentation) describes the reference. An agent that lands on either one can reach the other, and neither has to be rewritten when the other changes. Cloudflare does the same thing the same way — its root file opens by naming the other host ("For technical documentation, see developers.cloudflare.com") and later links it — with one gap: the link points at the HTML page, not at developers.cloudflare.com/llms.txt, so the agent has to discover the file from the convention rather than from the map.

Duplication: The GitHub 16-Byte Drift

GitHub takes the other route and serves both. The two files are nearly the same length — 28,658 and 28,642 bytes, a 16-byte difference — and both contain 117 links. They are not the same document. The H1 differs (# GitHub versus # GitHub Docs), the H2 count differs (12 versus 14), and the docs host carries a full ## Get started section that the root file does not have, complete with its own summary blockquote. Several entries also diverge: the root file links “About cloud agent” where the docs file links “Copilot on GitHub.com”, the docs file adds an “Individual plans” entry and drops “Chat in IDE”, and one MCP walkthrough points at a different path on each host.

That is what two generators fed by two manifests look like after a few months. Nothing is broken — every link resolves — but the two maps disagree about the product. If you duplicate, generate both files from one route list so the shared sections cannot drift; the split should be a filter, not a second editorial pass.

The .md Twins Landed on the Wrong Host

Cloudflare's root file lists 82 Markdown twins out of 90 links. Its docs host — where the reference pages actually live — lists 112 links and zero .md twins. So the host an agent reaches when it wants technical content hands over HTML URLs, while the marketing host hands over clean Markdown. The developers file compensates with a deeper tier: each product links its own scoped file (/argo-smart-routing/llms.txt, /cache/llms.txt), which is the right instinct — per-path splitting is exactly what the spec's path-scoping rule is for, and it is the same mechanic behind per-version files and per-language files.

The rule that follows: put the Markdown twins on the host that serves the pages, not on the host that sells the product. A .md twin is worth most where the content is deepest, and link hygiene on a multi-host estate means checking each file's links against the host that file lives on.

Redirects on the Root Path: Two Ways They Fail

Shopify's help centre redirects /llms.txt to /agents.md and serves 4,712 bytes of text/markdown. The body is a procedure rather than an index — it has four H2 sections and zero links, and it spends its words explaining that every public English page is available as Markdown by appending .md or by sending Accept: text/markdown. A redirect to a live document is fine; what it must not do is redirect to nothing. shopify.dev/llms.txt redirects to /llms.md and lands on an 80,728-byte HTML 404 — two requests, no file.

The second failure is a locale redirect on the root path. learn.microsoft.com/llms.txt 301s to /en-us/llms.txt and www.mozilla.org/llms.txt 301s to /en-US/llms.txt; both land on 404. If your edge stamps a locale onto every root path, exempt this one: the path is defined at the host root and has no language variant.

Four Rules for a Multi-Host Estate

The Five-Command Multi-Host Check

# 1. every host that owns content, in one pass
for h in example.com docs.example.com help.example.com; do
  curl -sS -o /dev/null -w "$h %{http_code} %{content_type} %{size_download} %{num_redirects}\n" \
    "https://$h/llms.txt"
done

# 2. where did the redirect actually land?
curl -sSL -o /dev/null -w "%{url_effective}\n" https://docs.example.com/llms.txt

# 3. which file does the root name?
curl -s https://example.com/llms.txt | grep -oE 'https://[a-z.]*example\.com/llms\.txt'

# 4. .md twins per host — the number should be highest where the pages are
for h in example.com docs.example.com; do
  echo -n "$h "; curl -s "https://$h/llms.txt" | grep -c '\.md)'
done

# 5. the 200-with-HTML trap: a SPA catch-all answers the path with a page
curl -s https://docs.example.com/llms.txt | head -1

Command 5 is the one that separates a real estate from a green dashboard. cloud.google.com/llms.txt answers 200, text/html, 41,682 bytes — with <title>404. Page Not Found</title> inside it. A status-code monitor reports a pass for a host that publishes nothing. Paste the body into the checker and you get the real answer in one step; build both hosts' files from the same sitemap with the generator and the drift problem never starts.