Why I Moved My Site from Hugo to Astro
For years my site ran on Hugo. Hugo is fast, stable, and honestly one of the best static site generators around. But I eventually hit a point where speed alone wasn’t the thing I cared about. I wanted a system that was simple, predictable, and didn’t force me into a templating model that felt heavier than the site itself.
The surprising part: I moved to Astro even though I don’t use React, Vue, Svelte, islands, or any client-side framework at all. My site is 100% static HTML. Astro is just a cleaner way for me to generate it.
This post covers why Hugo stopped fitting, why Astro clicked, and how the rest of my stack helps me understand what content actually resonates.
What stopped working for me in Hugo
Hugo never “broke.” It just made certain things harder than they needed to be.
1. The templating model felt heavy
Hugo’s Go templating language is powerful, but it always felt like Hugo’s logic instead of my site’s logic. Small layout changes required a surprising amount of mental overhead: partials, block inheritance, shortcodes, conditions, and layout resolution rules.
None of this is bad, but it’s a lot of machinery for a simple blog.
2. Reusable chunks of UI were awkward
Shortcodes work, but they never felt ergonomic. I often found myself rewriting small fragments because reusing them cleanly meant thinking through Hugo’s templating constraints.
3. Custom build steps didn’t fit cleanly
I generate analytics using DuckDB and Parquet files. Getting my own scripts to run inside Hugo’s world always felt bolted on.
4. The development loop slowed me down
Hugo is extremely fast, but the workflow around template editing never felt fast. I spent too much time navigating template indirection when all I wanted was straightforward HTML.
Why Astro works better for my (purely static) site
Most people talk about Astro because of the islands architecture. I don’t use any of that. What I do use is its extremely clean static-site model:
1. HTML-first, minimal abstraction
.astro files are just HTML with a tiny amount of logic at the top. It feels like writing actual pages instead of fighting a DSL.
2. Layouts are straightforward
No inheritance chain, no hidden magic. I just import a layout and render markdown inside it. And because .astro components are HTML, the layout logic stays obvious.
3. Zero JavaScript by default
Since I’m not adding interactivity, Astro ships no JS at all. I get a completely static site that feels lean and fast.
“Isn’t Astro just another templating system?” (Yes… but not really.)
You could argue that Astro and Hugo both have:
- layouts
- partials/components
- frontmatter
- template logic
- markdown → HTML pipelines
And at a surface level, that’s true. Both are static site generators, both ship HTML, and both involve some amount of templating.
But the difference, and the reason Astro clicked for me, is in the shape of the templating.
Hugo templates = a DSL with its own universe
Hugo uses Go templates, which come with:
- a custom syntax (
{{ .Something }},with,range,block,define, etc.) - implicit layout resolution rules
- shortcodes as a mini-language inside Markdown
- a strict separation between template logic and content
This power comes with a conceptual cost: once your site grows even a bit, you have to understand Hugo’s hierarchy to make safe changes.
Astro templates = just HTML + a little JS
Astro templates are:
- literally HTML files with a small script section
- explicit (components/layouts are imported, not magically resolved)
- readable without deciphering a DSL
- predictable because they render exactly what they look like
There’s no secondary template language to learn. No inheritance chain. No guessing.
The short version
Hugo’s templating is powerful but hierarchical and specialized. Astro’s templating is simple, explicit, and predictable.
Both are technically “templating systems,” but they feel completely different in practice.
My analytics stack: DuckDB + Parquet files
I don’t use Google Analytics, Plausible, or anything with tracking scripts. Everything is logs + files + SQL.
Here’s how it works:
- Request logs (Cloudflare + server logs) land in S3.
- A small script normalizes them and writes them to Parquet.
- I run local SQL queries with DuckDB.
DuckDB is basically SQLite for analytics. It’s incredibly fast and requires zero infrastructure.
What I track:
- Which posts attract returning readers
- Long-tail traffic for older content
- What posts unexpectedly take off
- Referrers that send people who actually stay
Astro made it easier to embed this analytics workflow into my repo without clutter.
The net result
Moving to Astro didn’t make my site look dramatically different. But it made working on the site dramatically nicer.
Since the migration:
- My layout code shrank
- Editing posts is simpler
- Making structural changes is trivial
- Build steps fit naturally in the repo
- The site stayed just as fast as Hugo, with less friction
I didn’t leave Hugo because it was bad. I left because Astro matches how I want to work now: small site, simple pipeline, clean HTML, no ceremony.
If your site is mostly static and you want something modern but minimal, Astro is an easy recommendation.