Why I Build on Astro
Contents
After my first clean build of this site, I ran a quick du -sh dist/. Under 150 KB. The whole thing (every page, every stylesheet, every asset) would fit on a 1996 floppy disk with room to spare. None of us are getting any younger ;-)
That number, more than any benchmark, is why I stayed.
I had been web-shopping for months. Eleventy, Hugo, plain HTML, even a brief flirt with a hand-rolled Python build. Every option had its grain. Astro is what I ended up shipping, and a few weeks in, I want to write down what worked and what got on my nerves a bit, in the spirit of a logbook, not a review.
Static, again
Astro is, at heart, a return to the static site. HTML is the artifact. Markdown is the source. The browser receives the page already built, and goes to sleep.
This is not a small thing. For fifteen years the industry told us static was insufficient: that we needed runtimes, hydration, a compute layer between the writer and the reader. The result is that a personal blog now ships a megabyte of JavaScript to render six paragraphs of prose.
Astro’s pitch is the inverse: ship nothing by default. If you want interactivity, opt in, island by island. I have not opted in yet, just to see. There is no JavaScript on this site that the browser is forced to run. The dark/light theme switches via prefers-color-scheme in pure CSS. The RSS feed is a static XML file produced at build. Dates render at build, not at runtime.
The framework’s most celebrated feature (partial hydration, the islands) is the one I have not needed, at least for now.
The prose-invert trap
The first real friction was cosmetic, and it cost me an evening.
I am using @tailwindcss/typography to style the prose. The plugin ships with sensible defaults: colors, spacing, a prose-invert mode for dark backgrounds. I had wired up my own CSS variables for theming (one set for dark, one for light, swapped via @media (prefers-color-scheme: light)), and watched the dark-mode prose render in dark-on-dark. Unreadable. Practice makes perfect, right?
The plugin had hard-coded its own palette under prose-invert, and it was winning the cascade against my variables. The fix was to bind the plugin’s CSS custom properties to my theme variables directly:
.prose {
--tw-prose-body: var(--text-color);
--tw-prose-headings: var(--text-color);
/* ...etc */
}
A handful of lines, declared outside @layer base so they win against the plugin’s own defaults. Obvious in retrospect, much less so at 11pm when you are new to a tool.
Lesson: when a framework offers a “dark mode” and you already have a theming system, expect them to fight. The cleaner contract is to let one own the palette and trust it.
Where the framework earns its keep
Three things in Astro that I would miss if it did not exist.
Content collections. Markdown files in a folder, a Zod schema for the frontmatter, and the build refuses to ship a post with a malformed date or a missing title. Editorial guardrails, for free.
The getCollection API. Listing posts, sorting them, filtering anything: three lines of TypeScript. No CMS, no database, no admin panel. The filesystem is the database. Simple and effective.
The RSS plugin. @astrojs/rss reads the collection and emits a valid feed. No manual XML, no template, no third-party service. The Small Web’s primary distribution channel, generated as a side effect of the build.
These features do not demo well. You end up not noticing them, but for a framework that is a fine compliment.
Tailwind v4, with caveats
Tailwind v4 was the other bet. The Vite plugin replaces the old PostCSS toolchain; configuration moves into CSS itself via @theme and @plugin. It is faster, cleaner, and the diff against v3 muscle memory was real.
The caveat: the documentation is mid-migration. Many tutorials online still assume v3. When something does not work, you are sometimes debugging the version, not the code.
If you are starting a project today, v4 is the right call. Just budget for some lost time of the “is it me, or am I reading v3 docs?” kind.
Why it fits the Small Web
A philosophy is worth what its tools embody.
Astro’s defaults match the Small Web defaults: no JavaScript shipped unless you ask for it; no tracking primitives; no cloud lock-in; the build artifact is a folder of files you could host on a small USB stick. The framework does not ask you to surrender sovereignty in exchange for ergonomics.
This is rarer than it sounds. Most modern frameworks assume you want to deploy on a specific cloud, route through a specific edge network, and hand your content over to a specific runtime. Astro lets you produce a dist/ folder and move on.
I write, push to main and walk away. CI builds the site, GitHub Pages serves it, and I turn the page.
That is all I ask of it.
Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.
Antoine de Saint-Exupéry, Terre des hommes, 1939
Update, May 20, 2026. Since this was written: a French version of the site, a second RSS feed, and dist/ now weighs around 400 KB. The 1996 floppy still has room.