This site ran until recently as a WordPress installation at a PHP webhost. I moved it in two steps: from WordPress to EmDash, and from that webhost to a Hetzner server I run myself. Both times, Claude carried the part that used to require expertise — WordPress internals, EmDash's API, Ansible — while I kept the judgment calls, especially around security. A third step moved the domains themselves to a different registrar and DNS provider.
Pulling the content
EmDash is supposed to replace WordPress for most use cases, in particular those with heavy plugin use, while not repeating the same architectural mistakes that made plugins in WordPress so error-prone. It is based off Astro.js, a framework I had already considered to base my next (mostly static) website on. I've been on WordPress for over a decade, and loved the ability to write small snippets of PHP to immediately get something; together with the free plugins I could find here and there WordPress was my go-to-platform. Security, of course, always sucked.
A few months ago I would have hesitated moving to anything not based on plain markdown files, since I was afraid of vendor lock-in and not getting my texts out of some weirdo database. Now I fear no longer, since LLMs are so absurdly good at transforming content from one form into another (and learning about arcane database layouts as well). So I was eager to just try something new.
EmDash ships its own WordPress importer, at /_emdash/admin/import/wordpress. I ran it once with a migration key: the first pass brought over 113 posts, 33 pages and every taxonomy, and stalled on media at 96 of 159 attachments. The importer is idempotent — it matches on slug and deduplicates by content hash — so a second run picked up the rest of the images.
Posts from the classic WordPress editor arrived as a single Portable Text block with \n\n inside the spans — looked right on the page, but wasn't a real paragraph. I also had to check with a SQL query where WordPress URLs were still hiding in the content:
SELECT COUNT(*) FROM ec_posts WHERE content LIKE '%konradvoelkel.com/wp-content%';18 posts and 8 pages matched, mostly featured_image values still pointing at WordPress.

Rebuilding the theme
I didn't want to keep the old WordPress theme, but I didn't want to reinvent it from scratch either — the isometric floorplan illustration above the header, the three-column image grid on archive pages, the centred reading column, all of that was already right. EmDash's own project scaffold wires up an MCP server with the current docs from the start (.mcp.json, https://docs.emdashcms.com/mcp, the search_docs tool) — it was already in place before I touched the theme. The feeling of changing the design was very much how I imagine working with a professional designer would be - but worse, of course. Nevertheless, being able to see the result and describing changes in plain English was faster and more fun than the HTML+CSS fiddling I actually used to enjoy, too.
From a webhost to my own server
The second step was bigger: from a managed PHP host to a Hetzner server I configure myself with Ansible. I barely knew Ansible going in. Claude had to explain the concepts to me, but didn't have to write every line for me, and every change could be tried out in a virtual machine first, before it touched the real server.
The test VM runs under plain QEMU/KVM, with a Debian 13 cloud image sized like the planned Hetzner server (8 vCPU, 16 GB RAM, 160 GB disk), SSH on localhost:2222, HTTP on localhost:8080:
make vm-start && make vm-bootstrap && make vm-site
git remote add vm ssh://admin@127.0.0.1:2222/srv/kv/repo.git
git push vm mainMy goal was to make the setup reproducible and to obtain fast closed feedback loops for Claude, so that I only have to specify measurable outcomes and let it explain the system to me. GitOps and Infrastructure-as-Code fit quite well.
The domains came along the same way: a move from Hosteurope to INWX.
INWX and Cloudflare and Hetzner all have APIs that Claude can work with, so I barely touched the overly complicated dashboards I used to fear with cloud service providers.
From DevOps to ClaudeOps
There's one exception: security. What a coding agent can check repeatedly and reliably — type checking, whether a build passes, whether a deploy checklist is ticked off — I let it check. For security-relevant decisions, like what belongs in the hardening role or how secrets are stored, I still want someone with real expertise to look it over too. An agent can tell me whether a rule was followed. Whether it's the right rule is still on me.
By the way, it is true what they say: a small VPS is not too expensive and fun to play around with. So much more flexible than a PHP webhoster!
