ReadableByAI
Menu ▾
Case file

A Menu on a Locked Door

By Alex Bouchard · 8 August 2026

The symptom

Seven companies in Y Combinator's Fall 2025 batch did the fashionable AI-visibility thing and skipped the fundamental one. They each publish an llms.txt file — the manifest that's supposed to hand AI systems a clean summary of what the site does — while serving raw HTML so thin it classifies as an empty shell to the same non-rendering crawlers the manifest was written for.

Zoom out and the pattern is bigger than seven. Of the 145 companies in this batch with a clean baseline, 48 (33%) publish an llms.txt. Separately, 37 (25.5%) serve CSR_SHELL raw HTML — under 150 visible words with no JavaScript executed, the threshold this audit uses for "there's nothing here to read." Widen the shell definition to include the next tier up — SSR_THIN, 150–399 words, still too sparse for reliable passage retrieval — and 51 companies (35.2%) are running thin or empty raw HTML. Ten of those 51 also publish an llms.txt. That's 10 of the 48 llms.txt publishers — 20.8% of everyone who did the trendy thing — sitting on top of raw HTML their own manifest can't rescue.

They wrote a menu. They just didn't check whether the door behind it opens.

The evidence (verify it yourself in twenty seconds)

llms.txt is a real file at a real path, and when it's present it's genuinely a well-formed, readable manifest — that part isn't fake. Here's what a representative site in the seven returns:

# The manifest, fetched plain:
curl -sL https://[example].com/llms.txt
#   → HTTP 200. A real, readable markdown file: product summary, doc links, pricing page,
#     use cases. Nothing wrong with it as a document.

# The homepage the manifest is supposed to be describing, same non-JS conditions
# every retrieval crawler actually operates under:
curl -sL https://[example].com | python3 -c "import sys,re,html; \
  t=re.sub(r'<[^>]+>',' ',sys.stdin.read()); print(len(html.unescape(t).split()))"
#   → 9 words.

Nine words is the median across the seven — not the worst case. Individually they run 8, 9, 9, 9, 30, 41, and 52 visible words of raw HTML. Any non-rendering crawler reading this raw HTML finds essentially nothing, regardless of what the llms.txt two directories over says exists. Status on both requests was 200. Nothing errored. Nothing looks broken in a status-code dashboard. The manifest is fine. The building it's taped to is empty.

Why this happens (it's not the founders being lazy)

Adding an llms.txt takes ten minutes: write a markdown file, drop it at the root, done. Fixing client-side rendering means touching your actual rendering pipeline — real engineering work, sometimes a framework migration. Given a choice between a ten-minute checkbox that a hundred blog posts told you was "AI SEO" and a multi-day refactor nobody told you was necessary, most teams will reach for the checkbox first. That's not negligence, that's incentives working exactly as designed.

The trouble is the checkbox doesn't do what the blog posts implied. In June 2026, Ahrefs looked at 137,210 domains that received traffic in May 2026 — 28% of those, roughly 38,000 sites, actually publish an llms.txt — and found that 97% of those ~38,000 files received zero requests in the month studied, nothing fetched them at all, bot or human. Google's John Mueller has said on the record that none of the major AI services have confirmed reading the file, and that "you can tell when you look at your server logs that they don't even check for it." No AI vendor's technical documentation lists llms.txt as something their crawlers consume. It costs nothing to add, so it's fine as a five-minute afterthought — but it is evidence-thin as a strategy, and it was never going to compensate for a homepage a crawler can't read anyway.

Blame the hype cycle, not the operator. Someone told these seven teams that publishing a manifest was the AI-visibility move. Nobody told them it was optional polish sitting on top of a prerequisite they hadn't met.

The fix (complete, free, no catch — same fix as the underlying problem)

Keep the llms.txt if you want; it costs nothing and does no harm. But it is not the fix. The fix is the same one every CSR_SHELL site needs regardless of what's in its manifest: make the raw HTML carry the content.

Next.js (App Router) — keep content in Server Components; push interactivity to the edges:

// app/page.tsx — a Server Component by default. This HTML ships fully formed.
export default function Page() {
  return (
    <main>
      <h1>What your product does</h1>
      <p>The actual pitch, in real text, in the raw HTML.</p>
      {/* Only the genuinely interactive parts become client components: */}
      <SignupWidget />  {/* "use client" lives inside this file only */}
    </main>
  );
}

Any SPA (React/Vue/Svelte) — add server-side rendering or static prerendering: Next.js, Remix, Astro, SvelteKit, or a prerender step (react-snap, Prerender.io) that bakes HTML at build time.

The test is the one from the curl command above, not the one about whether /llms.txt returns 200: the answer to "what does my product do" must exist in curl https://yoursite.com output. If you've fixed that and you still enjoy maintaining a manifest, go ahead — just don't let it stand in for the harder fix, and don't let anyone sell it to you as a substitute.

What it costs to mistake the menu for the door

Google's AI Overviews alone reach more than 1.5 billion users every month, per Alphabet's own Q1 2025 earnings remarks. That audience only ever sees content a crawler successfully retrieved and parsed — the manifest is not in that pipeline for any major system today. A beautifully written llms.txt sitting on top of a 9-word homepage reaches zero of those 1.5 billion, for the same reason a perfect restaurant menu behind a locked door serves zero dinners: the read has to succeed before anything downstream of it — citation, summary, recommendation — becomes possible at all.

How you'll know it's fixed

Run the two curl commands above against your own domain. /llms.txt returning 200 tells you your manifest exists. It tells you nothing about whether your homepage is readable — for that, run the second command, with JavaScript disabled, the condition every non-rendering crawler is actually in. Or run the free scan, which checks both — raw-HTML word count and llms.txt presence — across 12 crawlers, and doesn't let the second one paper over the first.

We'll re-verify you for free. Fix the raw HTML, reply to your notice (or email us), and we'll re-probe and publicly note the recovery. Keep the manifest if you like. Just fix the door first.

Method: each domain fetched with a baseline browser user-agent and 12 crawler user-agents (11 AI-vendor crawlers plus bingbot as a non-AI control) from a datacenter IP, seconds apart. Raw-HTML classification and llms.txt presence are both checked against a plain, non-spoofed fetch — identity-independent, so unlike bot-specific access results they need no server-log confirmation to cite as findings. llms.txt presence means an HTTP 200 at /llms.txt with a non-HTML body at time of probe; this audit does not and cannot measure whether any crawler actually requests that file on these domains — the 97%-unread figure cited above is Ahrefs' independent server-log study of a much larger domain set, dated June 2026, cited because no comparable log-level measurement exists for this batch. Full dataset and method: github.com/abouchard11/geo-crawl-audit.