Why I Removed Astro From My Stack: A Regression in Disguise
Astro's 'content-first' defaults ignore why routing was invented. Fast metrics aren't the same as respectful user experience — and TanStack Start brings me back to the present.

How Astro's default full-page refreshes taught me that "content-first" ignores a problem we solved 15 years ago — and why I'm consolidating to TanStack Start for everything.
A few days ago, I wrote about adding Astro to my stack. I was excited. The promise was clean: Astro for content, TanStack Start for apps, Hono for APIs. Each tool in its lane.
I was wrong.
Not about Astro being excellent at static content — it is.
I was wrong about what "content-first" really delivers when users start navigating.
I confused developer convenience with reader comfort.
I confused Lighthouse scores with actual human flow.
But more than that, I forgot a fundamental lesson of web history: routing was invented because full-page refreshes are a bad user experience. And Astro's default is to pretend that problem doesn't exist.
The Crack That Broke It
It started innocently. A client portfolio in Astro. Stunning first load. 100 Lighthouse. Everyone congratulated me.
Then I used it — not as the builder, but as a visitor.
Clicking to compare projects. Trying to keep a demo video playing while scanning details.
Every click: full page refresh.
Video stops.
Sidebar scroll resets.
Any in-page state: gone.
It felt like 2005. It felt like the web I'd fought to escape. It felt like a regression.
A Brief History We Forgot
Routing wasn't invented to make SPAs complex. It was invented to solve a real user problem:
- Navigation is good. The user wants to move to a new view.
- Refreshing is bad. It destroys context, interrupts playback, and resets state.
- Conditional rendering (hide/show divs) wasn't the answer. It breaks the URL, the back button, and deep linking.
We created routers to get the best of both worlds: new content, no refresh, intact state, and a functioning URL. Every major framework adopted this as the baseline for a respectful user experience in the 2010s.
Astro, in 2026, defaults to the pre-routing era.
What Metrics Hide
Astro sells "zero JS by default" as performance victory. And it is — for the very first visit.
But here's what no score tells you:
| Metric | What It Measures | What It Completely Ignores |
|---|---|---|
| First Contentful Paint | Initial page arrival | The next 20 internal clicks |
| Cumulative Layout Shift | First-load stability | Every reload flicker after that |
| Performance Score | Lab data on empty cache | Real-user frustration on repeated navigation |
My sites scored perfect.
My users still had a worse experience than any SPA I'd built before.
Because performance isn't only speed — it's continuity.
The SessionStorage Wake-Up Call
The real break came with form data loss.
A simple multi-step quote form across pages. Nothing fancy.
Built with Astro + React islands. "JS only where needed," right?
User goes step 1 → step 2.
SessionStorage wiped. Form progress gone.
This isn't a bug. It's how full-page refreshes work: new browsing context, new session.
Temporary state? Erased.
I wasted days on workarounds:
- localStorage (persists forever, wrong scope)
- URL params (ugly, limited length)
- Server sessions (overkill for client flow)
All to fight the framework's default navigation model. A model that ignores that we solved state persistence with routing over a decade ago.
The Layout Illusion
Astro has "layouts." You wrap pages in headers, sidebars, footers. Looks modern.
It's an illusion.
In TanStack Start (or any router-first framework), layouts persist. Header mounts once. Sidebar keeps scroll. Outlet swaps only content.
In Astro, layouts are templates. Every navigation: full re-render.
Header remounts. Sidebar collapses. Video restarts. Console clears.
Layouts without persistence are just fancy includes. They are not an evolution; they are a step backward to server-side includes from the 1990s.
The Docs Red Flag
I should have noticed sooner.
Astro's own documentation uses full-page refreshes between articles.
The creators — who could add
They choose refreshes for their own learning resource.
That tells you everything. If the framework's own documentation doesn't respect the reader's continuity, why would yours?
The Incentives Layer
Full refreshes = new request per navigation.
New request = edge hit.
Edge hits = metrics Cloudflare loves.
Cloudflare acquired Astro (early 2026).
Astro loves Cloudflare.
Both thrive on MPA patterns where every click generates cacheable traffic.
Not conspiracy. Just aligned incentives.
And those incentives favor full refreshes over persistent continuity. They favor a 2005-era technical model because it serves the infrastructure provider, not the user.
My users pay the price.
The Updated Reality Check
Revisiting the table from last time — with honesty:
| Aspect | TanStack Start | Astro (default) | What Actually Matters |
|---|---|---|---|
| Initial load | SSR + React bundle | Zero JS | Astro wins first paint |
| Subsequent navigation | Instant, no refresh | Full refresh, reset | TanStack wins every click after |
| Layouts / Outlets | True persistence | Re-rendered templates | TanStack keeps continuity |
| SessionStorage / State | Survives across routes | Cleared on nav | TanStack preserves user progress |
| Docs / Learning UX | Smooth, persistent | Disruptive refreshes | TanStack respects readers |
| Mental model | Unified, user-first | Content-first | Content-first ≠ reader-first |
| History Respect | Solves the refresh problem | Ignores it | TanStack learns from the past |
The Question That Mattered
Last time I asked: "Is your content serving the framework?"
Wrong question.
Right one:
Is your framework serving your users, or are your users serving someone's default that ignores 15 years of web progress?
Users don't care about zero JS. They care if:
- The video keeps playing
- Form data survives
- Sidebar stays open
- The back button works without a full reload
- Site feels built for humans in 2026, not servers in 2005
Astro defaults fail those tests.
What My Projects Actually Need
| Project Type | User Need | Best Fit |
|---|---|---|
| Portfolio | Smooth browsing, compare without resets | Persistent routing |
| Blog / Docs | Read without losing place/context | No refreshes |
| Marketing | Fluid exploration | Continuity |
| Client tools | Keep state across steps | True layouts |
These aren't "app-only" needs. They're basic 2026 expectations built on lessons we learned from the early 2000s.
The Performance Myth Revisited
"But SPAs ship too much JS!"
Thoughtless SPAs do.
TanStack Start doesn't:
- Code-splitting by route
- Lean router core
- Isomorphic loaders (server/client, no duplication)
- Streaming SSR when needed
I can build fast + persistent.
Astro forces me to choose fast or persistent.
The Consolidation
I'm removing Astro.
Not because it's useless — it's exceptional for pure static landing pages where navigation is minimal.
Because my projects need more than that.
They need sites that respect the user's context. They need to use the tools we invented to solve the refresh problem, not pretend that problem is a virtue.
Now:
- TanStack Start for everything (SSR/static + persistent routing)
- Hono for APIs
For content: TanStack's static gen + markdown. Takes setup time.
Worth it for no refreshes, real persistence, respectful UX.
Lessons Hard-Won
- Developer DX ≠ user UX. My quick setup doesn't matter if readers fight refreshes.
- Zero JS is a metric, not morality. A blank page loads fast. That's not victory.
- Layouts that remount aren't layouts. They're templates.
- Docs are the ultimate test. If a framework won't smooth its own docs, they're showing priorities.
- Incentives shape defaults. Follow them — and see who benefits.
- Routing was invented for a reason. Ignoring that reason isn't "content-first." It's history-blind.
Objections I Would Have Made (And Why They Don't Hold)
"Add View Transitions!"
Astro could default it for docs. They don't. Defaults reveal truth.
"Content sites don't need state!"
Scroll position is state. Open accordions are state. Form progress is state. Readers notice when lost.
"But it's MPA by design!"
Exactly. And MPA defaults are disrespectful for learning content in 2026. They ignore why we built better patterns.
Conclusion
I was wrong last time. Not about Astro's tech — about what matters most.
What matters is continuity. Respecting that users build mental context while navigating. Making tech invisible so content breathes.
Astro defaults make tech visible — painfully — with every refresh. They pretend that the problem of the full-page refresh, solved by routing, doesn't exist.
TanStack Start makes tech disappear.
That's the win.
One stack. One model. Defaults that serve users first and respect the history of our craft.
TanStack Start for everything.
Because "content-first" and "user-first" are not synonyms. And because ignoring the lessons of the past is a sure way to repeat its mistakes.
And I choose users.
If you're eyeing Astro for docs, blogs, or anything navigable: ask who you're really optimizing for. Your bundle size? Or are you ignoring 15 years of web progress?
Update March 15, 2026: This replaces my earlier Astro recommendation. Real usage changed my mind. Your mileage may vary — but my readers' experience didn't.