← back
Next.jsMigrationDevOps

From CRA to Next.js 16: Migrating a Production Site in One Session

The starting point

Tahetrükk.ee was running on React 17 with Create React App, Tailwind v2, served through Nginx in Docker. It worked, but it was stuck in 2021.

The goal: rewrite everything to Next.js 16 with App Router, TypeScript, Tailwind v4 — and migrate from a simple Docker + Traefik setup to a proper Kubernetes deployment with Helm charts and automated CI/CD.

What changed

  • React 17 → React 19 with Next.js 16 App Router
  • Tailwind v2 → v4 with the new PostCSS plugin approach
  • Nginx static serving → Next.js standalone output
  • Manual Docker build → GitHub Actions pipeline that builds, pushes to GHCR, and deploys via Helm
  • Traefik labels → Kubernetes Ingress with cert-manager for automatic TLS

The tricky parts

The case-sensitivity issue was the sneakiest: macOS doesn't care that Videos/ and videos/ are different, but Linux does. Git was tracking the old uppercase path, which would have broken the Docker build on the CI runner.

Result

Five static pages, zero JavaScript frameworks from 2021, and a deployment that takes care of itself.