How to fix a website that doesn't render without JavaScript
Retrieval crawlers and many AI search bots fetch the raw HTML your server returns. They generally do not execute JavaScript, wait for a framework to hydrate, or run client-side rendering the way a browser does, so 1 empty shell is all they read. Per Google's JavaScript SEO basics, the rule is plain: “if your answer needs JavaScript to appear, the crawler never sees it.” Serve your content in the initial HTML and verify it survives with JavaScript off.
The symptom: perfect in a browser, blank to a bot
Your page looks finished. You open it, the content loads, the headings are there, the article reads cleanly. Then a competitor with a thinner answer gets quoted in the AI result and you do not appear at all. When you check, your traffic from AI search is near zero even though the writing is better than what got cited.
This is the most common failure we catch, and it is invisible from inside a browser. The page works for you because your browser runs the JavaScript that builds it. The bot that decides whether to cite you does not.
The cause: the crawler reads HTML, not your app
When an AI engine or a search crawler fetches your page, it takes the raw HTML your server sends back over the wire. That is the document before any script runs. Retrieval crawlers and many AI search bots generally do not execute your JavaScript, wait for a framework to boot, or perform the client-side rendering pass that a real browser does.
A single-page app built on React, Vue, or Angular usually injects its content client-side. The server returns a near-empty HTML shell, often just a <div id="root"></div> and a bundle of scripts, and the actual text only appears after the browser downloads and runs those scripts. To a bot, that shell is the whole page. Your real answer is not in it.
So the bot sees nothing quotable, moves on, and quotes a competitor whose answer is sitting right there in the HTML. It is not that your answer was judged weaker. It was never read. This is a delivery problem, not a content problem, which is why writing more or better copy does not fix it.
The fix: put the content in the initial HTML
The goal is simple to state: your main content, your headings, and your links must exist in the HTML the server returns, before any JavaScript runs. There are three established ways to get there, and which one you pick depends on your stack and how often the content changes.
- Server-side rendering (SSR). The server runs your framework and returns fully rendered HTML on every request. Best when content is dynamic or personalized. Next.js, Nuxt, and SvelteKit all support this directly.
- Static site generation (SSG). Pages are rendered to HTML once at build time and served as flat files. Best for content that does not change per request, such as articles, docs, and marketing pages. It is also the fastest to serve.
- Prerendering for bots. A middleware step renders the page and serves the resulting HTML to crawlers while humans still get the live app. Use this when you cannot easily move the whole app to SSR or SSG. Serve the same content to bots and people, do not cloak.
Whichever route you take, the test of success is identical: the answer text, the headings, and the internal links are present as real HTML, not painted in later by a script and not baked into an image. If a person can read your answer only after JavaScript runs, so can only a browser, and the crawler is not a browser.
One more thing to check while you are in here: do not hide the content behind a click. Text that only appears after a tab switch, an accordion open, or a "load more" button often loads fine, but content injected by those interactions can still be missed. Lead with the answer in plain, server-rendered HTML near the top of the page. If you also want that answer to be quotable once it is readable, see how to make your content extractable for AI.
How to verify it: read the page the way the bot does
Do not trust the browser view. Trust the raw HTML. Here are three honest ways to confirm your fix worked, from fastest to most thorough.
- View source. Right-click the page and choose "View page source" (not "Inspect", which shows the rendered DOM). Search the source for a full sentence from your answer. If you find it, the bot can too. If you do not, it cannot.
- Disable JavaScript. Turn JavaScript off in your browser settings or with a toggle extension, then reload. What remains on the screen is roughly what a non-rendering crawler reads. If the page goes blank, that blank is what gets cited.
- Use an inspection tool. Fetch the URL with a tool that shows the raw response, or paste your link into Brimm. We fetch your page the way the engines do and tell you whether your answer survives without JavaScript, in plain language, in fix order.
Confirm the answer is present as text in all three. Confirm it is not an image of text, and confirm it is not injected after load. That is the whole bar.
Where this fits in the bigger picture
Rendering is one of several reasons a page that should be cited never is. The other two we see most often are crawler access, where the bot is blocked before it can fetch anything, and passage extractability, where the bot reads the page but cannot lift a clean, self-contained answer from it. If you are working through all of them, the Fix Library covers each one, and how to allow AI search crawlers is the right companion to this page. For the background on why AI answer engines reward readable, server-rendered content at all, start with what GEO is.
None of this is exotic. It is the same fundamentals search has always rewarded: be reachable, be readable without JavaScript, and be the most specific answer on the page. The render fix just makes sure the answer you worked on is actually in the document the machine reads.
Check your own page
You can run every check above by hand, or you can paste your link into our GEO audit and see in about 30 seconds whether your answer survives without JavaScript, whether the crawler can reach you, and how quotable your top passage is. We read your site the way the engines do and print the failures in fix order. Run the full audit in the app.