Career & InsightsSoftware Engineering

I Migrated My Portfolio from React to Next.js – Here’s What Changed (And What I Wish I Knew Earlier)

Shariar Shishir•September 27, 2026•5 min read
I Migrated My Portfolio from React to Next.js – Here’s What Changed (And What I Wish I Knew Earlier)

For months, my portfolio site was invisible to Google.

I had built it with React (Vite), deployed it on shared hosting, and thought the job was done. It looked great. It worked perfectly. Clients who visited the link loved it.

But here’s the thing – almost nobody was finding it.

After 3 months live, Google Search Console showed me the hard truth:

  • 78 impressions
  • 2 clicks
  • Zero queries ranking

For a developer with 16+ years of experience and 100+ shipped projects, this was embarrassing.


The Problem I Didn’t See Coming

React SPAs render everything client-side. When Google’s crawler visited my site, it saw an empty <div id="root"></div> and had to wait for JavaScript to execute before seeing any content.

Google can render JavaScript. But it’s slow, deprioritized, and unreliable for new domains with no authority.

Worse – every page served the same index.html. Same title tag. Same meta description. Same canonical URL. Whether you visited /services or /projects, Google saw identical metadata.

I tried workarounds:

  • A hidden #seo-content div with static HTML for crawlers
  • A PHP script (index.php) to dynamically inject meta tags before React loaded
  • Client-side usePageMeta hooks to update document.title at runtime

Each fix solved one problem and created two more.

The hidden div? Duplicate content across every route. The PHP injection? A “jora tali” (band-aid fix) that broke on edge cases. The runtime hooks? Invisible to any crawler that doesn’t execute JavaScript.

I was fighting the architecture instead of fixing it.


The Decision

I’d been avoiding Next.js because migration felt overwhelming. My site had 16 components, a WordPress headless blog, a contact form with MySQL + email, custom animations, parallax effects, and page-specific JSON-LD schemas.

But after months of SEO hacks, I realized I was spending more time on workarounds than a migration would take.

So I committed to it. One weekend. Full migration.


What the Migration Actually Looked Like

What stayed the same:

  • Every single React component (About, Hero, Projects, Contact, etc.)
  • All Bootstrap CSS and custom styles
  • All animations (react-awesome-reveal, react-countup)
  • WordPress headless blog integration

What changed:

Before (Vite + React)After (Next.js)
react-router-dom routingFile-based routing (app/about/page.jsx)
usePageMeta() hook for SEOexport const metadata — 3 lines
PHP script for meta injectionBuilt-in SSR — zero hacks
Hidden #seo-content divServer-rendered HTML — crawlers see everything
Static sitemap.xml fileAuto-generated from pages + WordPress API
index.html + index.phplayout.jsx — one file, done
Client-side blog fetchingServer Components — data fetched before HTML sent

The actual code changes per component? Adding 'use client'; at the top and replacing <Link to= with <Link href=. That’s it for most files.

The blog pages were the biggest win. Before, the blog loaded with a spinner while fetching from WordPress. Now, Next.js fetches posts server-side and sends complete HTML — every blog post is immediately crawlable with correct titles, descriptions, and Open Graph tags.


The Results

I deployed on Vercel (free tier) and pointed my domain. Within weeks:

Before (React SPA — 3 months):

  • 78 impressions
  • 2 clicks
  • 2.6% CTR
  • Position 5.9

After (Next.js — 3 months):

  • 176 impressions (+125%)
  • 5 clicks (+150%)
  • 2.8% CTR
  • Position 5.4

These numbers are still small. But the trajectory changed completely – the graph went from flat to climbing. Google is now discovering and indexing pages that were invisible before.

More importantly, every new page I add automatically gets:

  • Correct server-rendered meta tags
  • Its own canonical URL
  • Page-specific JSON-LD schemas
  • A sitemap entry

No hacks. No PHP scripts. No hidden divs.


What I Wish I Knew Earlier

1. Don’t fight your framework’s limitations – switch frameworks. I spent weeks building workarounds for React SPA’s SEO blindspots. The migration took a weekend.

2. Your components are portable. I reused 90% of my React code. The migration was mostly about where files live, not what’s in them.

3. Server-side rendering isn’t just about SEO. My blog pages load instantly now – no loading spinners, no layout shift. The user experience improved alongside the SEO.

4. Start with Next.js if SEO matters to you. If I was starting today, I wouldn’t build a portfolio with Vite + React. The SEO overhead isn’t worth it for a site that needs to be found.

5. “Good enough” SEO hacks become permanent debt. Every workaround I built had to be maintained, documented, and debugged. The Next.js approach is zero-maintenance.


The Stack Now

  • Framework: Next.js (App Router)
  • Hosting: Vercel (free tier)
  • Blog CMS: WordPress (headless, on existing hosting)
  • Contact Form: Next.js API Route + Nodemailer + MySQL
  • Styling: Bootstrap 5 + custom CSS
  • Animations: react-awesome-reveal

The old shared hosting still runs WordPress for the blog API. The main site lives on Vercel. Total additional cost: $0.


Should You Migrate?

If your React SPA is a portfolio, a business site, or anything that needs organic traffic – yes. The migration is smaller than you think, and the SEO difference is immediate.

If your site is a dashboard, an internal tool, or something behind a login – stay with Vite. SSR doesn’t help when there’s nothing to crawl.

For me, the decision was clear: I build web products for a living. My own site should reflect that I understand how the modern web works.

And it should be findable when someone searches for it.


I’m Shariar Shishir – a Full Stack Developer with 16+ years of experience building WordPress plugins, Joomla extensions, Laravel SaaS platforms, and React applications. If you’re planning a similar migration or need help with your web project.