Switching From Hugo to Astro

This site used to run on Hugo. As of last week it runs on Astro, and the switch took an evening. Two things about that are worth writing down: why I left, and how the leaving went, because the second one is the part I did not expect.
The honest version of why I left is that I never got comfortable with Hugo. I used it for a couple of years, it worked, it was fast, it never lost a post, and every time I opened the repo it was with a small feeling of dread about what I was going to have to look up to get a post out.
The clearest evidence sat in my own content folder. There was a draft post called “Hugo / Obsidian Blog Workflow”, dated February 2025. Title, date, tags, draft: true, and then nothing. Eighteen months of not writing the post about how comfortable I was with my setup. The workflow I was trying to build just never came together, and nothing else managed to take its place. That is a review in itself, if you are willing to read it as one.
The specifics are unremarkable, which is the point. The site was a third-party theme pulled in as a git submodule, which makes customizing it a negotiation with someone else’s markup. The config was a 152-line YAML file, of which 84 lines were keys with no value on them: blank settings for a theme’s features, sitting in my repo, doing nothing except being things I might be supposed to understand.
My favorite artifact of that file is that comments were turned off, and it still enumerated eight different comment providers. Disqus, DisqusJS, Utterances, Remark42, Waline, Twikoo, Giscus, Gitalk. Eight blank configuration blocks, in version control, for a feature I had disabled. None of which is really Hugo’s fault; it is aimed at people who want that surface area. It is just more machine than I need, and I never built the fluency that would have made it worth it.
The second half is the part I actually want to tell you about, which is that I didn’t really do the migration. Claude did, and what could easily have eaten a month of weekends landed as one commit on a Sunday evening. 191 files, about ten thousand lines added, six hundred deleted. Twelve posts (well, eleven posts and one shameful draft) and three pages carried across, the theme submodule gone, the 152-line config replaced by a src/lib/ directory where the logic is code I can read.
At this point, with AI’s help, speed is a given. The part that surprised me is which work got done because of the speed.
Think about migrating a blog by hand. You know the real risk is URLs: search engines and other people’s links point at the old paths, and Hugo was emitting paginated lists, per-tag pages, per-tag feeds and legacy aliases from an even older version of the site. You also know that cataloguing every one of those before you delete them is an hour of tedium standing between you and the fun part. Reader, on a Sunday evening you are not doing that. You are going to eyeball the homepage, click three links, and ship it.
What happened instead is that Claude audited 73 old URLs that went into a fixture file first, and that became a test that fails if any one stops resolving. Then a crawler that fails on any internal link, image or anchor that does not resolve. Then invariants on the content itself: every tag has a glyph, every post has a hand-written excerpt, no unconverted Hugo shortcodes anywhere. The suite is up to 331 tests, and it runs before every deploy.
That is the leverage that Claude brought. Not the speed directly, the confidence that I could cut over without breaking things. The boring, risk-reducing work is exactly what a motivated human skips at 7pm on a Sunday, and exactly what costs a machine nothing to be thorough about. I got the diligence I would have talked myself out of, and without it I probably would never have made the leap because it felt too risky.
There is a second-order effect too. Once building a small thing properly gets cheap, you build other things you would have put off: a JSON Feed alongside the RSS so the Bluesky cross-poster I also built reads structured data instead of scraping Open Graph tags out of my HTML, a scaffolder for new posts, a search index. None of those were really on a list anywhere, but I had the bandwidth to build them because my comprehension of the minutiae was no longer a blocker.
The stack now is Astro, MDX, static output, on GitLab Pages. The RSS feeds are unchanged, full content and all, because that was the one setting in those 152 lines I actually cared about.
I have no thesis about whether you should use Hugo; plenty of people are fluent in it and well served by it. But the tool I could not get comfortable with was costing me momentum on the very task I had brought it in to simplify, and the price of finding out if something else might work better had dropped to one evening.


