The mismatch
You open your React app in Chrome and see a fully rendered product page. A search crawler hits the same URL and gets back <div id="root"></div>. Same URL, completely different document.
How a browser renders your SPA
- The server returns a minimal HTML shell — a
<div id="root">and a<script>tag. - The browser downloads the JavaScript bundle.
- React executes, fetches data if needed, and writes the final DOM.
What a crawler actually receives
Most crawlers are not browsers. They make an HTTP request, read the response body, and move on — they do not execute JavaScript.
What they get: the raw shell. Your product names, descriptions, headings, and internal links are inside the JS bundle, unreachable.
Googlebot can execute JavaScript, but does so with a crawl delay and resource constraints that vary by site. Other crawlers — Bing, social bots for OG previews, RSS parsers, link unfurlers in Slack or iMessage — typically don't run JS at all. A broken OG preview in a chat is the most visible symptom.
Where prerendering fits in
Prerendering solves the problem at the server response level, before the crawler decides whether to run JS.
The flow with readypivs:
- A crawler hits your URL.
- readypivs intercepts the request, identifies it as a bot, and serves a pre-generated HTML snapshot instead.
- The crawler gets a complete document: real headings, real copy, real
<meta>tags, all internal links. - Real users get your normal SPA — nothing changes for them.
The snapshot is generated by running your JavaScript in a headless Chromium instance, so the output matches what Chrome would render. It is not a hand-crafted template.
CSS cleanup
Running a full Chromium render picks up all the inline styles and component-level CSS your app injected at runtime. readypivs removes the rules not applied to any element in the rendered output — making the snapshot lighter and faster to parse.
Meta tag overrides
SPAs typically set <title> and <meta name="description"> dynamically via something like react-helmet. A crawler seeing the shell gets whatever fallback values exist — often the <title>My App</title> you never customized.
Prerendering already handles the basic case since the JS ran before the snapshot was taken. For bulk control — pages from a CMS with wrong meta values, or URL patterns you want to update in one shot — readypivs includes an HTML Overrider: set title, description, keywords, and other meta fields per URL or via a regex rule, no code deploy needed.
Cache warming
The first request to any URL triggers a Chromium render, which takes time. readypivs eliminates that cold start by reading your sitemap.xml and pre-crawling every listed URL upfront. You choose between a lightweight fetch-based pass or a full Chromium-based one. After warming, every request hits a ready snapshot.
When prerendering is the right tool
- Your existing SPA works and migrating to SSR or SSG would be a large refactor.
- SEO and social sharing matter but you don't need per-user server rendering.
- You want bot-specific optimization without touching your frontend architecture.
It doesn't replace SSR for personalized server-rendered content, or SSG for fully static sites built at deploy time. But for most production SPAs, it's the shortest path to a crawler-readable site.
If you're new to the concept, the readypivs overview covers the basics.