February 8, 2026

Migrating my portfolio from CRA + Firebase to Next.js + Sanity: decisions, trade-offs, and lessons learned

Why I moved from CRA to Next.js and Sanity, what I actually gained in terms of SEO and content publishing, what the real costs were, and when I would choose Django instead.

Migrating my portfolio from CRA + Firebase to Next.js + Sanity: decisions, trade-offs, and lessons learned

This wasn’t a change “just because”

This decision didn’t start with technology.
It started with frustration.

My portfolio worked. It was fast, simple, built on a stack I knew well.
But the problem was simple: nothing came out of it.

It was a business card.
Not a tool.

What I actually needed was a place that lets me publish consistently, manage SEO consciously, and build a real personal brand over time — not just exist online.

The starting point was pragmatic

I began with React (CRA) and Firebase.
At the time, it made perfect sense: quick setup, low overhead, minimal configuration.

But once I started thinking about a blog — not a single article, but a system for writing — the cracks became obvious:

  • SEO was “good enough,” not intentional
  • publishing meant touching code every time
  • there was no real editorial workflow
  • the whole thing didn’t scale well as a content platform

That’s when the real question appeared:

Do I want to maintain a simple website,
or build a system that works for me long-term?

I considered three paths — none of them perfect

The first option was to stay where I was.
Lowest effort, fastest path forward.

But also the weakest foundation for SEO and long-term content growth.

The second extreme was full Django with a custom CMS.
Technically powerful.
Full control.
Clean domain logic.

And also: expensive in time, complexity, and operational overhead.
I wasn’t building a media company.
I was building a blog run by one developer.

The third option was a middle ground: Next.js with a headless CMS.
That’s where things finally started to align.

Why I chose Next.js + Sanity

This wasn’t about trends.
It was about trade-offs.

I wanted to:

  • publish fast,
  • control SEO per post,
  • avoid building an admin panel from scratch,
  • separate content from frontend logic,
  • keep performance high.

This stack delivered all of that without months of extra work.

Not perfect.
But pragmatic — and good enough where it mattered.

What I actually implemented

The migration wasn’t just a frontend rewrite.

It meant building a deliberate system:

  • multilingual routing,
  • full metadata per page and per post,
  • canonicals, Open Graph, JSON-LD,
  • dynamic sitemaps and robots,
  • a clean content model in the CMS,
  • a clear split: frontend renders, CMS owns content.

The biggest change?

Writing stopped being a technical operation.

What I gained — and what it cost

The most important outcome is simple:
publishing no longer hurts.

SEO is now a conscious decision, not an afterthought.
The structure supports consistency.
The whole setup makes sense as a long-term system.

The cost is real:

  • higher architectural complexity than a static site,
  • time spent on migration and polish,
  • discipline required to keep content consistent.

But this is a cost I chose intentionally.

Would I choose differently today?

Yes.

If I were building a product with heavy domain logic, complex workflows, and multiple editorial roles — Django would win without debate.

But for my actual goal:
an SEO-ready blog, fast publishing, and long-term personal brand building
this choice proved to be the right one.

Summary

This wasn’t a technical decision.
It was a decision about what role my website should play.

Not a nicer portfolio.
Not another side project.

A system that lets me think long-term — and show up consistently.