Pure Ranker
Technical GEOJun 4, 20267 min read

Why Client-Side Rendering Is Killing Your AI Visibility

AI crawlers like GPTBot and ClaudeBot don't run JavaScript. If your site is client-side rendered, here's why they see a blank page — and how to fix it.

Why Client-Side Rendering Is Killing Your AI Visibility

Here's a true story (names changed). A polished EdTech site — clean Next.js build, fast, beautiful — scored 48/100 on a GEO audit. The killer finding wasn't design or content quality. It was this: when you fetched the raw HTML, every page was nearly empty.

PageRaw HTML sizeServer <h1>Server body words
Homepage16.2 KB0~8 (title only)
Topic page20.4 KB0~12
Blog post17.0 KB0~9

Hundreds of lessons and articles — invisible. Why? Client-side rendering (CSR). If you're new to GEO, start with what GEO is and why it matters, then come back here.

What CSR actually does

With a CSR app (classic create-react-app, or a misconfigured SPA), the server sends a near-empty HTML shell plus a JavaScript bundle. The browser then runs the JS, which builds the page. Humans don't notice — their browser executes the script.

But here's the catch: many AI crawlers don't run JavaScript.

Who can and can't see your JS content

CrawlerRuns JavaScript?Sees CSR content?
Googlebot / GeminiYes (renders)Usually yes
GPTBot (ChatGPT)NoNo
ClaudeBot (Claude)NoNo
CCBot (Common Crawl)NoNo
PerplexityBot (fetch mode)Often noOften no

CCBot matters enormously: Common Crawl is a primary training corpus for many models. If CCBot sees an empty shell, your content may never enter the training data that shapes future answers.

So a CSR site is invisible to the biggest AI training and retrieval pipelines. You did all the work; the crawler reads a blank page.

How to check your own site in 10 seconds

curl https://yoursite.com/your-best-page | grep "<h1"

If your main heading and body text don't appear in the output, AI crawlers that don't render JS are seeing nothing. Open the page in a browser with JavaScript disabled for a visual gut-check.

The fix: render on the server

You want the real content in that first HTML response.

  • SSR (Server-Side Rendering): the server builds the full HTML per request. Great for dynamic pages.
  • SSG (Static Site Generation): pages are pre-built at deploy time. Perfect for blog posts and evergreen lessons — fastest and most crawler-friendly.
  • ISR (Incremental Static Regeneration): static pages that refresh on a schedule. Best of both worlds.

In Next.js App Router, Server Components render on the server by default. Use generateStaticParams to pre-build your /blog/* and content routes:

// app/blog/[slug]/page.tsx — a Server Component
export async function generateStaticParams() {
  const posts = await getAllPosts();
  return posts.map((post) => ({ slug: post.slug }));
}

export default async function BlogPost({ params }) {
  const post = await getPost(params.slug);
  return (
    <article>
      <h1>{post.title}</h1>
      {/* Real text in the server HTML — crawlers can read this */}
      <div>{post.body}</div>
    </article>
  );
}

Keep interactivity (quizzes, menus, app UI) client-side — that's fine. Just make sure the citable content — headings, body copy, key facts — ships in the server HTML.

Verify the fix

curl https://yoursite.com/blog/your-post | grep -E "<h1|<h2"

If your headings and paragraphs now appear in the raw response, you've unlocked the highest-leverage GEO win there is. In that EdTech audit, this single fix was projected to add +15–20 points.

Next up: once crawlers can read your pages, you guide them with llms.txt — the new robots.txt for AI.