Why I rebuilt everything in Astro
I spent a decade fighting page weight. Astro is the first framework that made the fast version also the easy version. Here is what changed, what I kept, and the three things I would not do again.
For most of my career, performance was a negotiation. You picked a framework you liked, shipped a pile of JavaScript to the browser, then spent the next month clawing seconds back: code splitting, lazy loading, arguing with a bundle analyzer at midnight. The fast version of a site was always the hard version. So most sites stayed slow.
Astro inverts that. The default output is HTML. JavaScript is the exception you opt into, one component at a time, exactly where interactivity earns its weight.
What actually changed
The mental shift is that a page is static until proven otherwise. You write components in whatever you already know, render them to HTML at build time, and the visitor gets a document, not a runtime.
---
// Static by default. This runs at build time, never ships.
import Hero from "../components/Hero.astro";
import Pricing from "../components/Pricing.tsx";
const plans = await getPlans();
---
<Hero />
<Pricing plans={plans} client:visible />
That client:visible directive is the whole philosophy in two words.
What I kept
- Write semantic HTML first.
- Keep TypeScript strict. The types are there to make deleting code safe.
- Measure on a real phone, not a gigabit connection and an M-series laptop.
The fastest site is the one that ships the least JavaScript it can get away with.
Three things I would not do again
One: do not port a heavy component just because it exists. Two: do not reach for a client framework out of habit. Three: do not skip the content layer.