← All posts
automationengineeringwordpressblogsself-hosting

Why I moved my blog off WordPress and into code

3 min readUpdated

For a while my blog lived on a free WordPress.com plan. 10 years to be exact — roboinno.wordpress.com, no custom domain, "Powered by WordPress.com" in the footer. Ads banner all around and to get rid of it I had to subscribe monthly. It worked, and it actually built something real: A community of people who were curious just like me. But the ads, constant limitations and lack of modifications made the experience really bad. So bad that I wanted to self host my own wordpress.

There are plenty of platforms where you can get a self-hosted WordPress blog running easily — Hostinger, for example, has genuinely cheap plans that give you a lot of control, though it adds up once you want something more serious. I looked at self-hosting WordPress on my Raspberry Pi instead, to get real code access. Docker, Cloudflare Tunnel, the whole setup — technically straightforward, a weekend project. But one Pi already runs my RL experiments and another home assistant. Putting a public-facing CMS — historically one of the most attacked platforms on the internet — on the same box as live trading credentials or my home assistant is a bad trade. Not because it's hard to secure, but because the asymmetry is wrong: worst case for a hacked blog is embarrassing, worst case for a hacked servers is real data and potentially money.

So instead, this blog lives right here, in the same codebase as the rest of the site:

  • Every post is a folder — public/blog/<slug>/index.mdx — with its own images sitting right next to it. No separate media library to keep in sync.
  • Frontmatter (title, date, excerpt, tags) is just YAML at the top of the file, parsed at build time.
  • No database, no admin login, no PHP. It's a static export — there's genuinely nothing here for an attacker to brute-force.
  • Writing is: open the .mdx file, write, save, flip to a browser tab, refresh. Next's dev server reruns the page's data loading on every request in development, so there's no build step in the way of seeing a draft.

The subscriber list moved too — into Firestore now, with double opt-in confirmation and self-service unsubscribe, no cap and no cost as the list grows.

This post is also the first real content in the new system, which means if you're reading it, the pipeline works. More about pipelines in a later blog.

Enjoyed this one? Get the next post by email — no spam, unsubscribe anytime.

Subscribe →