The itch
I ran this site on WordPress for years. It worked, in the way a rented house works: liveable, never quite mine. Every feature I wanted — a shop, a project timeline, multilingual pages — meant another plugin, another admin page that looked nothing like the last one, another thing to patch on a Sunday.
I build platforms for a living. At some point the gap between what I ship for clients and what I was running for myself stopped being funny.
What I built instead
The site you are reading is a small production system:
- Next.js 16 / React 19 for the public site — server-rendered, three languages, one design system
- ASP.NET Core 9 + PostgreSQL behind it — pages, blog, shop, timeline, all as structured content
- Keycloak for admin sign-in, with TOTP enforced — a personal site's admin panel deserves real MFA
- Ceph for media — uploads go straight to object storage over presigned URLs, so binaries never sit in the database or the container image
- Kubernetes on my own cluster, deployed by the same Gitea + Jenkins pipeline as every client project
Content lives in a database, not in deployments. When I edit a page, publish a post, or change a price, nothing rebuilds — the site simply reflects it.
The cutover
Swapping a live domain from WordPress to a new stack is mostly a redirects problem. Every old URL got a 301 into the new structure, DNS stayed put while the reverse proxy switched upstreams, and Search Console got a fresh sitemap the same hour. The old server is off. Nobody noticed the seam — which is the whole point.
What it costs
Honesty section: this is more system than a personal site needs. It needs a cluster, a pipeline, and an identity provider. But the site is also my workshop — the place I try patterns before they reach client work. The blog you are reading is the first tenant of that workshop.

Comments