Menu ▾
Case file

Invisible Without JavaScript

By Alex Bouchard · 8 August 2026

The symptom

37 of 145 companies in Y Combinator's Fall 2025 batch — one in four — serve a blank or near-blank page to every AI crawler that doesn't run JavaScript. The median among them shows 9 words of readable text before JavaScript executes. The three worst show one word.

GPTBot, ClaudeBot, and PerplexityBot do not run JavaScript. What they receive is the raw HTML your server sends — and for a quarter of this batch, that raw HTML is an empty shell. The product, the pricing, the pitch: all rendered client-side, all invisible to the models that increasingly decide who gets recommended.

These are not neglected sites. They are ~10 months out of the most competitive startup accelerator in the world, actively selling. They just shipped a single-page app and never checked what a non-rendering crawler sees.

The evidence (verify it yourself in ten seconds)

Here is what one representative site returns. The browser sees a full product page. GPTBot sees this:

# What a human browser is served (renders to a full page via JS):
curl -s https://[example].com | wc -w
#   → 6 words of raw HTML

# What GPTBot is served (same page, AI-crawler user-agent):
curl -s -A "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.2; +https://openai.com/gptbot" \
  https://[example].com | wc -w
#   → 6 words. The bot gets the same empty shell. There is nothing to read.

Status was 200 OK in both cases. Nothing failed. Nothing alerted. The page is "up" — it is simply empty to the reader that matters. (Full per-site status and word-count table in the Index.)

Why this happens (it's not incompetence)

Modern frontend frameworks default to client-side rendering. You run create-react-app or reach for a SPA template, ship it, and it works perfectly — in a browser. The browser runs your JavaScript and paints the page. Every human who visits sees exactly what you built.

The gap only appears for readers that don't run JavaScript, and until ~2023 that category barely mattered — Googlebot renders JS, so SEO didn't punish you. AI crawlers broke that assumption. GPTBot, ClaudeBot, PerplexityBot, and most others fetch raw HTML and never execute a line of your JavaScript. The default that was safe for a decade is now the single most common way to be invisible to AI. Blame the default, not the builder.

The fix (complete, free, no catch)

Server-render your content-bearing pages so the HTML arrives populated. Concretely:

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 simple: the answer to "what does my product do" must exist in curl https://yoursite.com output, not appear only after JS runs.

Structure that recovered content into extractable passages — a clear <h1>, definitions and value props in real <p> tags, the core answer in the first third of the page. That's where AI citations are drawn from.

What it costs to stay invisible

AI answer engines can only cite what they successfully retrieved. When Anthropic's crawler reads your page, it does so at a scale where it crawled roughly 70,900 pages for every visitor it referred — meaning the read itself, not the click, is the product. If the read returns an empty shell, you are absent from the answer while your competitor is present. For a company whose buyers increasingly start in an AI chat, that's not lost traffic — it's not being in the consideration set at all.

How you'll know it's fixed

Run the two curl commands above against your own domain. When the AI-crawler command returns your real content — not a shell — you're readable. Or run the free scan, which does this across 12 crawlers and reports the raw-HTML word count directly.

We'll re-verify you for free. Fix it, reply to your notice (or email us), and we'll re-probe and publicly note the recovery. "Invisible in the morning, readable by the afternoon" is a good story — and it's yours to tell.

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 visible-word count computed with JavaScript disabled (the condition every non-rendering crawler is in). Readability is identity-independent — it does not depend on which IP or user-agent asks — so unlike access findings, it needs no server-log confirmation. Full dataset and method: github.com/abouchard11/geo-crawl-audit.