KH.
Web DevWeb Dev
Web Dev··8 min read

From CSR to SSR: Why Your Portfolio Is Invisible to Google (and How I Fixed Mine)

My old portfolio was a Create React App. It looked fine in the browser. A friend who works in SEO looked at it and said: “Googlebot sees a blank page.” I didn't believe him until I ran a Lighthouse audit and got 62 out of 100 for SEO. The Performance score was worse.

What CSR actually sends to the crawler

In a client-side rendered React app, the server sends a response that looks roughly like this:

<!DOCTYPE html>
<html>
  <head>
    <script src="/static/js/main.abc123.js" defer></script>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

The actual content — your name, your services, your case studies — is all generated by JavaScript running in the browser. For a human on a fast connection, the experience is fine. The JS loads in under a second and React renders everything.

Googlebot has a different experience. It does crawl JavaScript — eventually. But the rendering is queued separately from the initial crawl and can happen hours or days later, or not at all for low-priority pages. During the initial crawl, Google sees your empty div#root and indexes that.

The practical result: your name, your experience, and your services might not be indexed at all. Or they might be indexed with a weeks-long delay, during which you rank for nothing.

The Core Web Vitals problem

CSR also tanks your Core Web Vitals, specifically LCP (Largest Contentful Paint) — the time until the page's main content is visible. With CSR, the browser has to download the HTML, then download the JavaScript bundle, then parse and execute it, then render the content. On a fast desktop connection you might get away with a 1–2 second LCP. On a mid-range Android device on a 4G connection in most of the world, you're looking at 3–5 seconds.

Google uses Core Web Vitals as a ranking signal. A slow CSR portfolio isn't just hard to find — it's penalized in search results relative to pages that are fast.

SSG, SSR, and ISR — which one?

Next.js gives you three rendering strategies. For a portfolio, the choice is straightforward:

Static Site Generation (SSG)is right for a portfolio. Your homepage, about page, and services pages don't change between requests. Next.js builds them at build time and serves static HTML. Googlebot gets the full content on the first crawl. LCP drops dramatically because the browser gets real content in the HTML, not an empty div.

Server-Side Rendering (SSR)renders each page on request. It's better for SEO than CSR, but slower than SSG because each request incurs a server render. Use SSR for pages that depend on request-time data (user sessions, personalisation). A portfolio doesn't need this.

Incremental Static Regeneration (ISR) is SSG with a time-based revalidation window. Good for blog pages that update occasionally — the page is static but Next.js regenerates it in the background every N seconds. I use ISR with a 24-hour window for my blog index.

The migration

I rebuilt the portfolio as a Next.js 16 App Router site. The architecture is straightforward:

  • Homepage, about, services, contact — all static (SSG at build time)
  • Blog index — ISR with 24-hour revalidation
  • Blog posts — SSG with generateStaticParams
  • OG image route — dynamic, edge runtime

The biggest concrete win was the LCP. My old CRA portfolio had an LCP of 4.2 seconds on a simulated Moto G4 in Lighthouse. The Next.js SSG version runs at 1.1 seconds on the same simulation. That's not a configuration win — it's a fundamental architecture difference.

What actually improved in search

I ran the old CRA site for about 18 months. In Google Search Console, it showed 12 indexed pages and essentially no impressions for anything meaningful. After switching to Next.js SSG and giving Google 6 weeks to re-crawl:

  • Indexed pages: 12 → 31
  • Search impressions: negligible → ~400/month
  • Lighthouse SEO score: 62 → 100
  • Lighthouse Performance (mobile): 48 → 91

Is 400 impressions/month impressive? No. But it's a starting point that can grow. The CRA version had no starting point at all.

The takeaway

If you're a developer with a portfolio built in Create React App, Vite, or any other purely client-side setup — switch to Next.js SSG. It's not a difficult migration, and the SEO and performance difference is significant. The tools exist. There's no good reason to be invisible to search engines in 2026.

The irony of a developer's portfolio being unfindable via Google is real, and it's entirely avoidable.

Newsletter

DevOps dispatches, when I have something worth saying.

Occasional long-form on Kubernetes, CI/CD, and infrastructure. No filler, no cadence commitment.

Kamal Hussain

Kamal Hussain

Freelance DevOps & cloud engineer. Kubernetes, CI/CD, AWS, and web development for startups across the US, EU, and MENA.