LovableSEO
Technical Guide

SEO for React SPAs: How to Get Indexed

A React single page app ships an empty HTML shell and renders everything in JavaScript. Search engines see a blank page. Here's how to fix that and actually rank.

Why React SPAs Struggle with SEO

A traditional server-rendered website sends complete HTML to the browser. The page content is right there in the response. A search engine crawler reads it, indexes it, and moves on.

A React SPA works differently. The server sends a minimal HTML file, usually just a <div id="root"></div> and a JavaScript bundle. The browser downloads the JavaScript, executes it, and only then does your content appear on screen.

This is the core problem: when Googlebot fetches your page, it gets an empty HTML shell. Google does have a rendering engine that can execute JavaScript, but it runs in a separate queue with delays, it has resource limits, and it does not always render everything correctly.

What Googlebot actually sees

View source on any React SPA and you'll see the problem. The HTML contains no headings, no paragraphs, no meta descriptions pulled from your router. Just an empty div and a script tag. That's what the crawler gets on the first pass.

The specific issues that client-side rendering creates for SEO:

  • No content in initial HTML. Crawlers may not wait for JavaScript to execute. Your page appears empty.
  • Missing meta tags. React Helmet or similar libraries inject meta tags via JavaScript, but crawlers read the raw HTML first. Title tags, descriptions, and Open Graph tags may not exist in the initial response.
  • No crawlable links. If your navigation uses JavaScript event handlers instead of real <a href> tags, Google cannot discover your other pages.
  • Rendering budget limits. Google allocates limited resources to render JavaScript. Large bundles, API-dependent content, and slow rendering can cause Google to give up before your page fully loads.
  • Delayed indexing. Even when Google does render your SPA, it happens in a second wave. New content may take days or weeks to appear in search results instead of hours.

How Google Actually Crawls SPAs

Google uses a two-phase indexing process. Understanding this is key to fixing SPA SEO.

Phase 1: Crawling. Googlebot fetches the raw HTML of your URL. It reads the content, follows links, and extracts metadata. For a server-rendered page, this is enough. For a React SPA, this phase finds almost nothing.

Phase 2: Rendering. Google sends the page to its Web Rendering Service (WRS), which is essentially a headless Chromium browser. WRS executes your JavaScript, waits for the DOM to settle, then sends the rendered HTML back for indexing. This second phase is resource-intensive and runs on a separate queue.

The gap between Phase 1 and Phase 2 can range from seconds to weeks, depending on your site's crawl budget and Google's current queue. During that gap, your content is effectively invisible.

This is why pre-rendered or server-rendered HTML matters. If Google gets the content in Phase 1, there is no delay. Your pages can be indexed immediately.

3 Solutions for React SPA SEO

There are three proven approaches to making a React app visible to search engines. Each has different trade-offs in terms of complexity, performance, and cost.

1. Server-Side Rendering (SSR) with Next.js

The most comprehensive solution. Next.js renders your React components on the server and sends complete HTML to the browser. Crawlers see fully rendered pages on the first request.

Best for: New projects where you can choose your framework. Next.js also gives you static site generation (SSG), incremental static regeneration (ISR), and API routes.

Trade-off: If you already have a React SPA built with Create React App or Vite, migrating to Next.js is a significant rewrite. Routing, data fetching, and build configuration all change.

Effort: High for existing apps (full migration). Low for new projects (start with Next.js from day one).

2. Static Site Generation (SSG)

Pre-render every page at build time and serve static HTML files. Frameworks like Gatsby, Astro, or Next.js with getStaticProps can generate HTML for each route during the build step.

Best for: Content-heavy sites with pages that do not change frequently. Blogs, documentation sites, marketing pages.

Trade-off: Does not work well for highly dynamic content (user dashboards, real-time data). Build times grow with page count. Requires a rebuild to update content.

Effort: Medium. Requires a framework that supports SSG and a CI/CD pipeline for builds.

3. Prerendering Service (Dynamic Rendering)

Keep your SPA as-is and add a prerendering layer in front of it. When a search engine crawler requests a page, the prerendering service intercepts the request, renders the JavaScript, and returns the fully rendered HTML. Regular users still get the normal SPA experience.

Best for: Existing React SPAs where you cannot or do not want to rewrite the entire application. This is the fastest path to SEO for apps already in production.

Trade-off: Adds a dependency (the prerendering service). There may be a slight delay between content changes and cached prerendered versions. Some services charge per-page.

Effort: Low. DNS or proxy configuration, no code changes to your React app.

Technical SEO Checklist for React Apps

Regardless of which rendering approach you choose, every React app needs these technical SEO fundamentals in place.

Unique title tags per page

Every route needs its own title tag (50-60 characters) with the primary keyword. Use React Helmet, Next.js metadata, or your framework's equivalent. Never use the same title across multiple pages.

Meta descriptions

Write a compelling 150-160 character description for each page. This is what appears in search results below your title. Without one, Google generates its own, and it usually misses the point.

Canonical URLs

Set a canonical URL on every page to prevent duplicate content issues. SPAs with query parameters or hash-based routing are especially prone to creating multiple URLs for the same content.

XML sitemap

Generate a sitemap.xml listing all indexable URLs with last-modified dates. Submit it to Google Search Console. For SPAs with client-side routing, this is critical because Google cannot discover pages by following JavaScript-based navigation alone.

Schema markup (JSON-LD)

Add structured data to help Google understand your content type. Article, FAQ, Product, Organization, and BreadcrumbList schemas enable rich results in search. Embed JSON-LD in your page head or body.

Open Graph and Twitter cards

Add og:title, og:description, og:image, and twitter:card tags so your pages look good when shared on social media. These tags also influence how AI search engines display your content.

Proper status codes

SPAs often return 200 for every URL, even 404 pages. Configure your server or CDN to return proper HTTP status codes. A soft 404 (200 status with “page not found” content) confuses crawlers and wastes crawl budget.

Use real anchor tags for navigation

React Router's <Link> component renders real <a> tags, which is correct. But custom navigation using onClick handlers with navigate() creates links Google cannot follow. Always use href attributes.

The Easiest Fix: Use a Prerendering Service

For most React SPAs already in production, prerendering is the pragmatic choice. You keep your existing codebase, add a proxy layer that detects crawler requests, and serve pre-rendered HTML to search engines while real users get the normal SPA experience.

The setup typically works like this: point your domain's DNS to the prerendering service. When a request comes in, the service checks the user agent. If it's Googlebot, Bingbot, or another crawler, the service renders the page with a headless browser and returns the HTML. If it's a normal user, the request passes through to your SPA unchanged.

Popular prerendering options

  • Prerender.io — One of the oldest dedicated prerendering services. Works with any SPA framework. Pricing is per-page.
  • Rendertron — Open-source prerendering server from the Chrome team. Self-hosted, so you manage the infrastructure, but no per-page fees.
  • Cloudflare Workers — You can build a custom prerendering layer using Workers and Puppeteer. Maximum control, but requires development effort.
  • LovableSEO — Purpose-built for React apps deployed on platforms like Lovable. Handles prerendering, meta tags, sitemap generation, and schema markup through a DNS proxy. Also publishes SEO-optimized blog content automatically.

What to look for in a prerendering service

Not all prerendering services are equal. Here's what matters:

  • Cache freshness. How quickly does the cached version update when your content changes? Stale caches mean Google sees outdated content.
  • Meta tag injection. Some services can inject or modify meta tags, title tags, and canonical URLs without touching your code.
  • Sitemap generation. Ideally the service generates and submits sitemaps for you rather than requiring you to build and maintain your own.
  • Schema markup support. Structured data should be present in the pre-rendered output, either from your app or injected by the service.
  • Content publishing. Some services go beyond prerendering and can publish blog content on your domain, which is the most effective long-term SEO strategy.

Mistakes That Kill SPA Rankings

These are the patterns we see consistently in React SPAs that struggle to rank:

  • Relying on Google's rendering alone. Google can render JavaScript, but it's slow, unreliable, and resource-constrained. Do not bet your SEO on it.
  • Hash-based routing. URLs like example.com/#/about are not crawlable. Google ignores everything after the hash. Use HTML5 history-based routing (example.com/about).
  • Loading content from APIs without fallback. If your page content depends on an API call that takes 3 seconds, the crawler may time out before seeing anything. Pre-render critical content or provide initial HTML.
  • Mega bundles. A 2MB JavaScript bundle takes time to download and parse. Google's WRS has resource limits. Code-split your app so each page loads only what it needs.
  • Ignoring Core Web Vitals. Largest Contentful Paint (LCP) and Cumulative Layout Shift (CLS) matter for rankings. SPAs that render a loading spinner before showing content will have poor LCP scores.
  • No content strategy. Even with perfect technical SEO, a React SPA with only product pages will not rank for informational queries. You need content (blog posts, guides, resources) to capture organic traffic.

The Bottom Line

React SPAs are not inherently bad for SEO. The problem is that client-side rendering creates a gap between what users see and what search engines see. Close that gap with server-side rendering, static generation, or prerendering, and your React app can rank just as well as any server-rendered site.

For existing apps, prerendering is the fastest path. For new projects, start with a framework like Next.js that handles rendering out of the box. Either way, do not skip the technical SEO basics: meta tags, sitemaps, schema markup, and real anchor tags.

The sites that rank are the ones that make it easy for Google to understand their content. Do the work, and the results follow.

Need SEO for Your React App?

LovableSEO handles prerendering, meta tags, sitemaps, schema markup, and automated content publishing for React apps. Set it up in 5 minutes with a DNS change.

As featured on

Live on FoundrListFeatured on ufind.bestFazier badgeFeatured on Twelve ToolsFeatured on Wired BusinessFeatured on Dofollow.ToolsGood AI ToolsAcid ToolsLovableSEO - Featured on Startup FameFeatured on Findly.tools