reactseo.com All posts
SSR Apr 12, 2026 8 min Mara Voss

Why your CSR React app is invisible to Google

Most React teams ship a client-rendered app, drop a few <title> tags into a useEffect, and assume Google will sort it out. It usually doesn't.

This piece walks through what Googlebot actually does with a CSR bundle, where it gives up, and the smallest possible change that gets your routes indexed.

#How Googlebot really renders JavaScript

Googlebot uses a two-pass indexing model: an initial HTML crawl, then a deferred render pass using a recent Chromium. The render pass is queued — sometimes seconds, sometimes weeks.

If your initial HTML is an empty <div id="root" />, the first pass indexes nothing. You're entirely at the mercy of the render queue.

#Where CSR quietly breaks

  • Meta tags injected after mount are often missed by social crawlers entirely.
  • Routes behind client-side data fetches return blank HTML to the first crawl pass.
  • Soft 404s appear when a route renders a loading skeleton instead of real content.

#The minimum viable SSR fix

You don't need to rewrite the app. Server-render the shell, the <head>, and the above-the-fold content for indexable routes. Hydrate the rest.

tsx~/minimum-viable-ssr.tsx
export const Route = createFileRoute("/posts/$slug")({
loader: ({ params }) => fetchPost(params.slug),
head: ({ loaderData }) => ({
meta: [
{ title: loaderData.title },
{ name: "description", content: loaderData.excerpt },
],
}),
component: PostPage,
});

#Verify before you ship

Use the URL Inspection tool in Search Console on a fresh route. Check the rendered HTML, not just the screenshot. If your <h1> and primary copy aren't in the source, neither pass of indexing will see them.

// next up

Killing LCP regressions with React Server Components

How to use streaming SSR and selective hydration to keep Largest Contentful Paint under 2.5s on real devices.

Read article