From WordPress to Hugo to Astro
Table of Contents
It started because of the complexity, honestly.
For years, this blog ran on WordPress. It was the sane choice at the time, but over time, it became a burden. It was a pain to maintain, constantly demanding updates for plugins I barely remembered installing. Styling it was fighting against a codebase I didn’t control. And all of that, I was paying Dreamhost $130 a year.
The result? I just stopped writing. For years. A number of very expensive years.
The Great Export
In March 2024, I was done. I was getting out. I exported everything from the WordPress database into Markdown files (using wordpress-export-to-markdown)
That sounds simple, but the reality was a mess. I wrote a slew of python scripts to convert the database Markdown dumps to clean them and correct Markdown. I’d write a script scanning the content directory cleaning one small thing at a time, reviewing, committing, and modifying the script… in order to break as little as possible.
I’m still cleaning it, fixing broken images and dead links even tonight. But at least the content is editable again, and safe in git.
The Hugo Detour
I looked around at alternatives, and chose Hugo. I was excited to learn some Go, and the promise of a static site generator that blazed fast appealed to me. I wanted a theme I could tear apart and extend. I had considered Pelican, but felt like getting out of my Python wheelhouse (wheelhouse… get it?)
It was going fine for a good long while. I had my markdown corrected, I had a decent theme, and yet…
I hit a wall. I got a basic site up and running, but while trying to add to the site, I kept going around and around trying to figure out if the configuration was part of Hugo, or the theme. And it was frankly confusing. Changing themes? Be prepared to reconfigure the site. Again.
Not to be overly negative, but it was fairly frustrating. To be very specific, some of what Hugo does is standardized, and yet much more is left to individual theme developers. Too much in my opinion. If I were in charge, I would be bringing in, and standardizing as much as the “core platform” as possible, and not leaving so much of the operational functionality in theme developer’s hands. But they didn’t. So for each different theme, came an entirely new set of configuration options, that didn’t work like the previous theme. Granted, I understand that will be the case to a degree, but this was an much larger degree than allowed me to be productive.
However, at least I stopped paying the $130/yr! I moved everything to Cloudflare’s free pages.
Landing on Astro

So I went searching again and found Astro.
It wasn’t just the architecture. After wading through the muck of a messy content migration, ripgrepping and scripting until my eyes bled, the speed of Vite and the safety net of TypeScript felt like a warm blanket.
I also really appreciated the template system. It felt like the MVC frameworks I grew up on. It reminded me enough of Django to make me happy.
TypeScript is… fine. It’s more typing than Python, and it feels like it has more friction than the elegant languages I prefer, but it works. I hate the closing braces, it’s not XSLT, but it’s not Python whitespace either. And the testing? It feels bolted-on compared to pytest, but maybe that’s just me.
That said, what I really like is Zod. While I didn’t do much Hugo exploration here, exporting out of Wordpress, the frontmatter of my markdown files was… not a mess, but messy. Unkempt. Using Zod to define the schema took some data cleansing, but really helped me get to a place where my automated tests, or even Astro itself, can remind me when I’m creating a new document and using the wrong schema. Plus it meant that my 100+ posts were all correctly formatted, and that I didn’t have to worry about an improper type breaking my render logic. That’s a huge relief. I need to get back to tightening down my schemas (i.e. removing overly lenient .optional() permissions), but it’s still a huge help.
The Tailwind Problem
To get this thing shipped, I started with the Astro Nano theme. It’s great, but it’s built on Tailwind CSS.
Look, I championed OOCSS. Back when we refactored PubMed.gov, we crushed thousands of lines of CSS down to a few hundred using patterns. We ported that to PubMed Central with barely 80 lines of new code. That system worked for over 100 developers because it relied on architecture, not reinventing the wheel every time you needed a button.
Tailwind feels like the opposite. It feels gross. Cluttering my markup with a soup of utility classes? It destroys readability. It feels like a regression. It hurts my soul.
Future Plans
Ripping it out is next on my list. I want a codebase that feels crafted, not just assembled from a kit.
But for now? We’re live. It’s fast. It’s free. And I’m actually having fun pushing boundaries, like my GasPrices page that pulls data into a readable repo, or my SportsFeed that uses Cloudflare Workers to fetch data on-demand.