Why does a React single-page app hurt SEO?
A React single-page app hurts SEO because the server sends an almost empty HTML file and the browser builds the page with JavaScript. Crawlers that read the first response see a title, a script tag and an empty div, not your headings, copy or links.
This is one of the most common early-startup mistakes we see. The product was built with Create React App or Vite, someone added a homepage and a pricing page to the same app, and the marketing site inherited the app's rendering model. It works fine for users and quietly fails for search.
Fixing it is usually part of a bigger question: should marketing pages stay in the product codebase at all? Our hub on moving from code to a visual builder covers that decision. This guide covers the diagnosis and the fixes.
Doesn't Google render JavaScript now?
Google does render JavaScript, but rendering happens after crawling, it can be delayed, and anything that fails during rendering is invisible. Relying on it for your most important pages adds risk you don't need. Google's own JavaScript SEO basics explain the crawl, render and index stages.
AI answer engines are the bigger issue now. Many AI crawlers fetch the raw HTML and don't execute JavaScript, so a client-rendered page gives them nothing to quote. If you want to be cited by ChatGPT, Perplexity or Google's AI features, your answers need to be in the HTML. We go deeper in server-side rendering for AI crawlers.
Social previews break the same way. Link-preview bots for Slack, LinkedIn and X read meta tags from the first response, so tags set by JavaScript after load often never appear.
How do you check whether your React site has an SEO problem?
Check by comparing what your server sends with what the browser shows. If the two differ a lot, crawlers are seeing the smaller version.
View the page source
Open view-source on your homepage and pricing page. If you can't find your headline or body copy in the HTML, the content is client-rendered.
Fetch without JavaScript
Load the page with JavaScript disabled or with a command-line request. An empty page means crawlers that don't render get nothing.
Use URL Inspection
In Google Search Console, inspect a key URL and view the crawled page's HTML and screenshot to see what Googlebot rendered.
Check indexing
Look at Search Console's page indexing report for pages marked crawled but not indexed, or indexed without your real titles.
Test link previews
Paste a URL into a messaging app or a social preview checker and see whether the right title, description and image appear.
These checks are your ranking evidence. Save screenshots and the indexing report before you change anything, so you can compare after the fix. Our website migration SEO checklist lists what else to capture.
What are the ways to fix SEO on a React SPA?
There are four ways to fix it, from a quick patch to a proper rebuild. They differ mostly in who will edit the site afterwards and how long the fix lasts.
Fix | How it works | Effort | Lasts |
|---|---|---|---|
Prerendering service | Serves cached HTML snapshots to bots | Low | Stopgap only |
Static prerender in your build | Generates HTML for marketing routes at build time | Low to medium | OK for a few static pages |
Move to Next.js or Astro | Static generation or server rendering per page | Medium | Long term, stays in code |
Rebuild in Framer or Webflow | Builder publishes static HTML | Medium | Long term, marketing owns it |
If your marketing pages are a handful of static routes, a build-time prerender can buy time. If the site is growing, with a blog, case studies and landing pages, pick one of the two long-term options.
When should you move the marketing pages to Next.js or Astro?
Move to Next.js or Astro when engineers will keep editing the marketing site and you want to reuse your React components. Both send full HTML on the first request, which solves the crawling problem at the root.
Next.js suits teams whose marketing pages sit close to the product, with shared components, auth-aware navigation or live data. Astro suits content-heavy sites that are mostly static, because it ships no JavaScript unless a component needs it. Our comparison of Next.js vs Remix vs a Vite SPA explains when an SPA is still the right choice, which is for the logged-in app, not the marketing site.
After moving, use the framework's metadata features for titles, descriptions, canonicals and Open Graph tags on every page. Our Next.js SEO checklist covers metadata, sitemaps, rendering modes and schema.
Splitting the SPA from the marketing pages
You don't have to convert the whole app. The usual pattern is to keep the product as an SPA on app.example.com and move only the public pages to a new project on example.com.
List every public route first: home, pricing, features, blog, legal pages. Those go to the new site. Anything behind login stays in the SPA. Then redirect any old public paths that change, and update links in the app that point to marketing pages.
When is Framer or Webflow the better fix?
Framer or Webflow is the better fix when marketers should own the site and engineers would rather focus on the product. Both publish static, server-rendered HTML, so the SEO problem disappears along with the engineering queue.
This is the right call for a lot of early-stage SaaS teams. The React SPA usually happened because an engineer was the only person who could build pages. Moving the marketing site to a builder fixes the SEO problem and the bottleneck that caused it. Our guide to moving a Next.js site to Framer shows the rebuild and routing steps, and they apply to a React SPA too.
The trade-off is that components can't be shared with the product, and some interactive pieces become embeds. For a marketing site made of pages, a blog and forms, that rarely matters.
How do you run a React SPA SEO migration without losing what ranks?
Keep URLs identical, carry every title and description into real HTML, and redirect any path that changes, including hash-based routes. Then compare the new site's raw HTML with your screenshots from before.
The irony of an SPA migration is that you're rarely losing much ranking, because the old pages weren't fully visible to begin with. The bigger risk is breaking links people already share and bookmark. Treat every public URL as something to preserve, even if it has no search traffic today.
- Hash routes. If old URLs used /#/pricing, search engines treated them as the homepage. Move to clean paths and update internal links.
- Trailing slashes. Pick one form and redirect the other.
- Sitemap. Generate one from the new site and submit it in Search Console.
- Separate the app. Put the SPA on a subdomain so app routes stay out of the index; our guide to splitting the marketing site from the app covers the options.
