1,182 Blocks. Twenty-two years. One enlightening evening.
My website turned twenty-two this year. The first post went up in November 2003. The last one went up in July 2018, and then nothing happened for eight years, which is a long time for something to sit on the internet doing nothing but existing.
Then in July, WordPress core got a vulnerability with a name. wp2shell — unauthenticated remote code execution on a default install, no plugins required. Thirteen minutes after the advisory went public, people were already trying it on strangers' websites. But here's my favourite part: I was fine. My install was so far behind that it never got the feature the exploit goes through. I wasn't safe because I'd patched anything. I was safe because I was lazy and didn‘t care. Eight years of ignoring a website, quietly working as a security strategy 😅
Still, finding out that neglect is the only thing standing between you and a vulnerability, as big as this one, is not a great feeling, even when the maths works out in your favour. So I finally moved what was long overdue. WordPress to Kirby, over about two weeks. What came out the other end was 1,182 blocks — every post, every image, every pull quote from twenty-two years of nested ACF in a WordPress database that still had the b2_ prefix from times before it was even called WordPress, sorted out of one long heap and into text files I can actually open with a click.
That's what a migration really hands you. Not code. Years of decisions nobody ever made, all coming due at once.
Nobody decided any of this
Old projects aren't messy because people wrote bad code. They're messy because a thousand small decisions got made without a proper scope, and nobody ever wrote them down. Yeah, and also because the same stackoverflow-snippet was carried over for years and years to come.
Nobody decided my RSS feed should have HTML inside the post titles — which it did, for years. Nobody decided a class called .mono should render in a sans-serif. Nobody decided that I should add my main stylesheet twice. It just happened, and then it was existing in the loneliness of the internet for years, and nobody told me. Including me.
That's what a migration really hands you. Not code. Years of decisions nobody ever made, all coming due at once. "Ausmisten", another beautiful German term for things like this. Literally: to muck out a stable.
And here's the uncomfortable bit: point an AI agent at that pile and it will make hundreds more of them an hour. Plausible ones. Confident ones. Completely invisible ones. Next session it makes different ones, because it doesn't remember and you still haven't written anything down. That's what slop actually is. Not stupidity — the same debt as before, produced industrially, in a nicer font.
That evening I made one very good choice, using a skill that looked promising to muck out the stable. Deciding things before I built anything, grilling me lightly to catch the scope of things to come and writing down little tasks for a proper handoff.
The boring evening
So the fix isn't a better prompt. It's changing what you hand over. Not a task. A decision that has already been made.
I used /wayfinder, a skill by Matt Pocock. It plans the decisions, not work: you name a destination, break it into tickets that each hold exactly one question, and the map is finished when the deciding is finished. The building is a separate job, on purpose.
The first hour felt like a comedy central show: The roast of… my mess, my years of laziness, my small decisions and my stackoverflow-snippets. Then something happened that paid for the whole evening. I had written down, confidently, how many of my posts were link posts, a parser for nested ACF to Markdown and added a lot of clever ideas on how to port it into Kirby blocks. The audit ticket that the map itself had spawned came back ten minutes later — before a single line of converter code existed. I was amazed by it and was feeling a similar confidence too.
The payoff is slightly embarrassing. Once a ticket carries its own context — the paths, the field names, what done looks like, and what it must not do — the model doesn't have to be clever. It has to be obedient and deliberate. I charted with an expensive model for the map and handoff-tickets, then ran most of the grind on a small, cheap agent that burns a fraction of the tokens, and it was spot on, over and over again.
You don't buy a better model. You write better tickets, and then you can afford a worse one. Thanks Matt 👏
Hey Claude, while you’re on it…
I was coming back from our summer vacation in Sardinia and had a bunch of nice photos from that trip laying on my Instagram. So the idea grew to just augment my website with some new features. Now that I have this shiny new foundation with such a confidence-brimming agent, why not?
The same evening, I had my first collections of images. The agent added my lightbox of choice, EXIF modals, light/dark modes, grid-lanes etc. It was a blast, I loved it. Which is exactly the thing I'd just spent the whole time arguing against. It felt fantastic. That's what makes it a bit dangerous and could backfire later.
Why Kirby is such a great choice, again.
One thing I did not expect. WordPress kept my writing in a database — to let anything near it, you export XML, go through phpMyAdmin 😬 or go through an API. Kirby keeps it in text files, right next to the templates, so an agent can simply read it. Fix a heading, check four hundred pages for a dead link, rename a field everywhere. Changes show up in a git diff like everything else. And whatever comes after Kirby, my writing leaves in the shape it's already in.
It's also why the Förderverein site was such a pleasant build — an agent that can open the content directly is a different kind of collaborator.
That wasn't why I picked Kirby. It might be the best thing about it after all.
The branch and the saw
I've called myself a designer and developer for a long time. Both halves of that just got handed to something that works cheaper and faster than I do, and I'm the one who handed them over.
What did not get handed over: saying no to my own spec. Deleting a feature the agent was proud of. Noticing that a GPS map on a family photo is a privacy risk, not a feature. Thats a smaller and sometimes annoying task, but a necessary one. The machine did the typing. That one evening did the deciding. Swap those two around and you get the slop that everyone hates.
There's a joke here about sawing off the branch you're sitting on. I'd write it out properly, but I'd probably ask an agent how the phrase is correctly written in english, and that rather makes the point 😬
I practised on the one project where being wrong costs nothing — a blog where nothing was happening for years, where the worst case was wasting my evening. That was deliberate, i can recommend it. You should try it out one day ✌️