If you’re reading this, it worked.
This post is a test of a new publishing setup — but it’s also the story of why I needed one. My blog had been live for a while and I’d written almost nothing on it. Not for lack of things to say. The problem was friction.
The old way, and why it lost
The blog was hand-built static HTML. Each post was a markdown file, which was fine. The catch was a second file — index.json — that listed every post’s title, date, summary, and path. Publishing meant:
- Write the markdown.
- Re-type all that metadata into
index.json. - Match up image paths by hand.
- Commit and push.
The listing page only read index.json, not the markdown. So if I forgot to update the JSON — easy to do — the post just silently didn’t appear. And JSON is unforgiving: one trailing comma and the whole blog breaks. It was the kind of small, dumb friction that’s enough to make you not bother. So I didn’t.
What I changed
I rebuilt the site on Astro. Two things made the difference.
The index builds itself. Astro has “content collections” — it reads the markdown files directly and generates the listing from their frontmatter. The index.json is gone. Adding a post is now just dropping a markdown file in a folder. There’s nothing to keep in sync because there’s nothing to sync.
A CMS so I don’t even touch files. I added a browser-based editor. I log in with GitHub, write in a text box, hit publish — and behind the scenes it commits the markdown to my repo, which triggers a build and deploy. No editor, no terminal, no git. I can write a post from my phone.
The rest of the migration was plumbing: the shared nav and footer became real components, the standalone tools moved over untouched, and the whole thing still deploys the same way it did before — a static build pushed to my server. Same hosting, better workflow.
The part I learned something from
The CMS needs to log me into GitHub, and that requires a secret that can’t live in the public site. The fix was a tiny piece of code — about forty lines — whose only job is to hold that secret and complete the login handshake.
The interesting bit is where it runs. I deployed it as a Cloudflare Worker — serverless. I didn’t rent a machine or keep a process alive. I handed the platform a function and got back a URL. It sits idle until someone logs in, runs only then, scales on its own, and costs nothing at my volume. It was the first time the term “serverless” clicked for me as something concrete rather than a buzzword: there are still servers, I just never had to think about one.
The takeaway
The lesson wasn’t really technical. It was that friction quietly kills habits. The blog didn’t fail because writing is hard — it failed because publishing had four annoying steps. Remove the friction and the habit has a chance.
So: new post, written in a text box, published with one click. We’ll see if it sticks.