Open your site and it looks finished. Fetch it the way a crawling assistant does — one plain HTTP request, no browser, no JavaScript engine, a hard timeout — and a client-rendered application returns something close to this:

<div id="root"></div>
<script src="/assets/index-4f2a91.js"></script>

That is the whole of what the assistant has to answer from. Not a degraded version of your page: nothing. And no error is produced anywhere — the status is 200, your monitoring is green, your analytics show nothing unusual, because the visitor never arrived to be counted.

How common is this

Of 293 well-known public sites measured on 2026-09-03, this many ship a shell and assemble the page in the browser:

11 of 293 (4%)of well-known sites return an app shell rather than content to a plain HTTP fetch

The median page in the sample carries 673 readable words. The client-rendered ones carry a fraction of that, and it is almost never the fraction the owner would have chosen.

But Google renders JavaScript. Doesn't everyone?

No, and this is the assumption that costs the most. Google Search has run a rendering pass for years, which is why client-rendered sites can rank perfectly well and why nobody notices the problem through their SEO tooling.

The crawlers behind AI assistants generally do not. They are optimised for breadth and for latency — an answer engine fetching a page while a person waits cannot afford to boot a browser — so the overwhelmingly common behaviour is: request, read, move on. Your Lighthouse score and your search ranking will tell you nothing about this, because they are measuring a different reader.

This is also why AXRAY deliberately runs no browser. Rendering the page would flatter you and would describe a world no crawling agent lives in. The constraint is the product.

What to actually do about it

You do not have to abandon your framework. You have to make sure the first response already contains the content, which every modern framework can do.

StackWhat to reach for
Next.js (App Router)Server Components by default; keep use client to the leaves that genuinely need interactivity.
Next.js (Pages Router)getStaticProps for anything that can be static, getServerSideProps for the rest.
NuxtSSR mode, or nuxi generate for pages that do not change per request.
SvelteKitDefault SSR. Check you have not set export const ssr = false on a route that matters.
AstroAlready server-first. Use islands only where interaction is needed.
Vite / CRA SPAA prerender step for the public routes, or move the marketing pages to a static generator.
WordPress, Shopify, WebflowAlready server-rendered. Check that a theme or app has not moved a key section into client-side JavaScript.

You do not need to convert the whole application

The pages an assistant is asked about are a small, predictable set: the home page, what you sell, what it costs, who you are, how to get in touch, and your documentation. A signed-in dashboard can stay a client-rendered application forever — nobody is asking ChatGPT about it. Fix the public surface and leave the app alone.

How to check without taking anyone's word for it

You can do this yourself in one command. If what comes back is a shell, you have found it:

curl -s https://your-site.com | grep -c "<p"

Or run the whole check — the fetch, the word count, the structured data, and the reconstruction of exactly what an assistant comes away with:

npx axray-cli your-site.com --context

See the text an assistant actually receives from your page, and what it can and cannot say about you from it.