# Why AI can't see your React/Next site — and the fix

> An SPA serves AI bots an empty HTML shell: GPTBot and PerplexityBot don't run JS. How to check what the bot sees and make your content AI-visible.

_Source: https://seomatrix.ai/blog/geo-for-spa/ · Updated: 2026-06-26_

---

You invested in content, yet AI answers never mention you. Often the cause is technical: the site is an **SPA** (a Single-Page App on React, Next.js in CSR mode, Vue, Svelte) where content is drawn in the browser. The catch: **AI bots don't run JavaScript** — so they see an empty page.

> In short: if content only appears after JS runs, it doesn't exist for GPTBot and PerplexityBot. No text, nothing to cite.

## What an AI bot actually sees

GPTBot, OAI-SearchBot, PerplexityBot and ClaudeBot read the **source HTML** of the server response. They don't wait for hydration and don't click. If your `<div id="root"></div>` is filled by a script, the bot gets a shell with a stray "You need to enable JavaScript to run this app" — and leaves.

**Check in 10 seconds:** paste a URL into [How AI sees your page](/tools/ai-view/) — it shows the exact no-JS text and how many words are hidden behind JavaScript. If a browser sees 1,500 words and the bot gets 11, that's your GEO problem.

## How to fix it — by framework

The goal is the same: **ship rendered content in the first server HTML response.**

- **Next.js** — use SSR, SSG or ISR (`getStaticProps` / App Router server components) instead of pure client-side. Content must be in the HTML before hydration.
- **Nuxt** — `universal` (SSR) or `nuxt generate` (SSG) instead of `ssr: false`.
- **React (CRA / Vite SPA)** — move content pages to prerendering (Astro, Gatsby) or add server rendering. Pure CSR is wrong for content that must be cited.
- **Vue / Svelte** — SvelteKit and Nuxt do SSR/prerender out of the box; enable it for public pages.
- **Dynamic rendering** — as a stopgap you can serve bots prerendered HTML (Prerender.io and the like), but honest SSR/SSG is more reliable.

> Rule of thumb: content pages → SSR/SSG. Interactive apps (dashboards, logged-in apps) can stay SPAs — they aren't cited anyway.

## After rendering — finish the GEO job

Once the bot sees text, add the rest:

1. **Schema.org (JSON-LD)** — `Article`, `FAQPage`. Build valid markup in the [schema generator](/tools/schema-generator/).
2. **llms.txt** — a site map for AI engines. How-to in the [llms.txt post](/blog/llms-txt/).
3. **AI-bot access** — make sure `robots.txt` doesn't block citation bots: [AI-crawler access check](/tools/ai-access/).
4. **Citable paragraphs** — [a direct answer in the first 1–2 sentences of each section](/tools/geo-check/). More in the [complete GEO guide](/blog/geo-guide/).

## Where to start

1. Run your key URLs through [How AI sees your page](/tools/ai-view/).
2. If the bot sees a shell — turn on SSR/SSG for content pages.
3. Re-check with the same tool and add schema + llms.txt.

> Want an autonomous AI team to do this for you — from diagnosis to publishing? See the [home page](/) or the [comparison](/compare/).

## Sources

- Google Search Central docs (JavaScript SEO, rendering), OpenAI GPTBot and Perplexity — on AI crawlers reading source HTML.
- llmstxt.org, Schema.org.

## FAQ

### Do AI bots execute JavaScript?

Mostly no. GPTBot, PerplexityBot, ClaudeBot and most AI-answer crawlers read the source HTML and don't run JS. If content is client-rendered, the bot sees an empty shell.

### Googlebot renders JS — isn't that enough?

Googlebot does render JS (with delay), but AI Overview and third-party engines (ChatGPT, Perplexity) often take content from the source HTML. For GEO you need content in the first server response.

### How do I check what the bot sees fast?

Paste a URL into our free 'How AI sees your page' tool — it shows the exact text an AI bot gets (no JS) and how many words are hidden behind JavaScript.

