Why I Build Everything With Astro Now (And Stopped Reaching for Next.js)

After shipping a dozen production sites, I've learned that islands architecture and minimal JavaScript beat universal JavaScript every time.

An opinionated take on building modern websites with Astro, Tailwind, Alpine.js, and Netlify. Learn why less JavaScript ships faster, what actually breaks at scale, and when this stack isn't enough.

Jay McBride

Jay McBride

Software Engineer

9 min read
Support my work on Buy Me a Coffee

Introduction

I’ve rebuilt this blog three times. First in Next.js. Then Gatsby. Now Astro.

Each time, I thought “this framework will finally be fast enough.” Each time, I was wrong. Next.js shipped 200KB of JavaScript for a blog that didn’t need any. Gatsby built in four minutes and broke every time I updated dependencies.

Then I tried Astro. Zero JavaScript by default. Builds in 15 seconds. Ships HTML that loads instantly. When I need interactivity, I add it surgically with Alpine.js instead of hydrating the entire page.

This article is for developers who’ve shipped production sites with modern frameworks and are questioning why everything feels so heavy. If you’re just learning web development, this isn’t your starting point. Go build something with Next.js first, then come back when you’re tired of debugging hydration errors.

I’m going to tell you why I default to Astro now, when this stack breaks down, and what I’d build differently if I started over. No “works for me” anecdotes. Just what ships fastest with the least complexity.

Enjoying this? 👉 Tip a coffee and keep posts coming

Here’s who this is for: Developers building content sites, marketing pages, documentation, and SaaS landing pages. People who’ve noticed their blog loads slower than it should. Teams shipping static-first applications.

Not for: People building heavily interactive applications like dashboards or collaborative tools. This assumes you understand when JavaScript is actually necessary.

The question isn’t “what’s the best framework?” It’s “why am I shipping so much JavaScript?”


The Core Judgment: Default to Zero JavaScript Unless You Need It

Here’s my default recommendation after shipping a dozen sites: build with Astro for static-first architecture, add Tailwind for styling without CSS complexity, and sprinkle Alpine.js only where you actually need client-side interactivity.

Not theoretical. Surgical.

Most frameworks ship JavaScript by default and let you opt out. Astro does the opposite. Zero JavaScript unless you explicitly hydrate a component. This single architectural decision fixes most performance problems before you write a line of code.

I’ve built the same site in Next.js and Astro. Next.js bundle: 180KB. Astro bundle: 3KB (just Alpine for the mobile menu). Same functionality. Same design. Users couldn’t tell the difference except the Astro version loaded instantly.

JavaScript frameworks are optimizing for the wrong thing. They optimize for developer experience—hot reload, component libraries, familiar patterns. But they do it by shipping megabytes of runtime to every user. Most sites don’t need React on every page. They need HTML that loads fast and works without JavaScript.

The mistake people make is thinking “we might need interactivity somewhere” means “we should hydrate everything.” No. You add interactivity where you need it. A modal doesn’t require React hydration. Alpine handles it in 2KB. A form doesn’t need client-side routing. Just POST to the server.

I see this constantly: teams use Next.js for blogs and marketing sites where 90% of pages are static content. They’re paying the cost of universal JavaScript—bundle size, hydration time, complexity—for features they don’t use.

The decision isn’t “which framework is more powerful?” It’s “how much JavaScript am I willing to ship for this use case?”

If you’re building a real-time dashboard, use Next or SvelteKit. But if you’re building content sites, marketing pages, or mostly-static SaaS pages, Astro ships faster because it ships less.


How This Works in the Real World

The reason Astro feels different is that it breaks your mental model of modern frameworks.

You think every page needs hydration. You think components need to be interactive by default. You’re used to shipping JavaScript to render anything dynamic.

Here’s what actually happens with Astro’s islands architecture:

You write components in React, Vue, Svelte, whatever. Astro renders them to HTML at build time. By default, that’s it. No JavaScript ships. The user gets static HTML.

When you need interactivity, you add a directive: client:load, client:idle, client:visible. This tells Astro “ship JavaScript for this specific component only.” The rest of the page stays static. No unnecessary hydration. No framework runtime unless you explicitly need it.

You combine this with Alpine.js for simple interactions. Dropdowns. Modals. Accordions. These don’t need React. They don’t need hydration. Just a tiny library that handles DOM manipulation directly.

What surprised me when I went all-in on Astro:

  1. Build times dropped by 10x. Next.js took 3-4 minutes to build 100 pages. Astro does it in 20 seconds. This matters for deploys and for preview builds during content edits.

  2. Lighthouse scores hit 100 consistently. Not with optimization tricks. Just by default. Static HTML is fast. Zero JavaScript on most pages means no execution cost. No hydration means instant interactivity.

  3. Content editors loved it. With Decap CMS, they edit markdown files in a Git-based workflow. Every edit triggers a preview deploy on Netlify. They see exactly what the change looks like before it goes live. No WordPress admin panel. No database. Just files.


A Real Example: When Complexity Was Killing Us

I built a documentation site for a client in 2023. They needed search, versioning, and API references. I chose Next.js because it felt like the “professional” choice for something complex.

Three months in, builds took five minutes. The search bundle was 150KB. Versioning required manual routing configuration. Every page loaded slowly because of hydration. The client asked why their docs were slower than competitors using Jekyll.

I rebuilt it in Astro with Algolia for search. Builds dropped to 30 seconds. Search was a tiny Alpine component that queried Algolia directly—no React bundle. Versioning became directory-based routing with no configuration. Pages loaded instantly because they were just HTML.

What I’d do differently: Ask “does this actually need a JavaScript framework?” before starting. Documentation sites are content. They need fast load times and good SEO. They don’t need universal JavaScript. Astro was the right tool from the start.


Common Mistakes I Keep Seeing

Hydrating components that don’t need it. Teams add client:load to everything “just in case.” This defeats the entire point of islands architecture. Only hydrate components that genuinely need client-side state or interactivity.

Using heavy component libraries. If you’re importing a full React component library for a few buttons and forms, you’re shipping hundreds of KB for no reason. Use Tailwind for styling and build simple components yourself. Or use lightweight libraries like Headless UI with Alpine.

Over-engineering content workflows. Teams want headless CMSs with GraphQL APIs for blogs that update twice a month. Decap CMS stores content in Git as markdown. It’s simple, version-controlled, and has zero runtime dependencies. Unless you need multi-region editing or complex permissions, Git-based CMS is enough.

Treating build time as irrelevant. “Builds take 10 minutes, so what?” This matters when you’re iterating on content or fixing bugs. Fast builds mean faster feedback loops. Slow builds kill productivity and make deploys risky.


Tradeoffs and When This Stack Isn’t Enough

I’m not saying Astro works for everything. I’m saying it works for most content-driven sites.

Use Astro when:

  • You’re building content sites, blogs, documentation, or marketing pages
  • Most pages are static with occasional interactive components
  • You want fast load times and perfect Lighthouse scores by default
  • Your team prefers simplicity over flexibility

Don’t use Astro when:

  • You’re building a heavily interactive application (admin dashboards, collaborative tools)
  • Most pages require authentication and per-user dynamic content
  • You need real-time updates or WebSocket connections everywhere
  • Your team is deeply React-native and doesn’t want to learn a new build model

Real limitations of this stack:

  • No server-side rendering for dynamic content. Everything is static or client-side. If you need per-request HTML generation, use Next.js or Remix.
  • Git-based CMS doesn’t scale for large editorial teams. If you have 50 editors making simultaneous changes, you need a real headless CMS with a database.
  • Alpine.js is simple but limited. Complex state management or nested components are painful. When you hit this, reach for a proper framework.

The honest answer: if 80% of your site is content and 20% is interactive, Astro handles it beautifully. If those percentages flip, use a different tool.


Best Practices I Actually Follow

Keep most components static. Write components without client-side JavaScript first. Only add client:* directives when you hit a concrete need for interactivity.

Use Alpine for simple interactions. Modals, dropdowns, tabs, mobile menus—Alpine handles these in a few KB. Don’t reach for React unless the interaction requires complex state.

Optimize images aggressively. Astro’s image component handles responsive images and lazy loading automatically. Use it. Images are usually the bottleneck, not JavaScript.

Leverage Netlify’s edge features. Redirects, headers, and preview deploys are built-in. Use them instead of building custom solutions. Edge functions handle light server-side logic when you need it.

Measure what actually ships. Check your bundle size with every PR. Set budget limits. If a component adds 50KB, question whether it’s worth it. Small bundles stay small through vigilance, not accident.


Conclusion

JavaScript frameworks aren’t bad. Universal JavaScript is overused.

Next.js, Gatsby, and SvelteKit are powerful tools for applications that genuinely need them. But most content sites don’t. They need fast load times, good SEO, and simple deployment. Astro delivers this by defaulting to static HTML and adding JavaScript only where necessary.

After years of fighting with heavy frameworks, I’ve learned that shipping less JavaScript means shipping faster and maintaining less complexity. The hype moved to universal frameworks, but static-first architecture kept working—and now it’s thriving because developers are rediscovering what simple means.

The future isn’t “static or dynamic.” It’s choosing the right amount of JavaScript for the actual problem you’re solving.

Start with zero JavaScript. Add it surgically when you need it. Your users will notice the speed. Your team will notice the simplicity.


Frequently Asked Questions (FAQs)

Can Astro handle e-commerce or authenticated applications?

Partially. You can build marketing pages and product listings in Astro, then handle cart and checkout with client-side JavaScript or redirect to a dedicated checkout page. For full authenticated experiences, use Next.js or Remix with server-side rendering.

How does Astro compare to Next.js for SEO?

Astro is better by default. Every page is pre-rendered HTML with no hydration delay. Next.js requires careful configuration to match this. Both can achieve good SEO, but Astro gives it to you for free.

What about content preview for non-technical editors?

Decap CMS has a preview mode that shows live changes as editors type. For production previews, Netlify generates a unique URL for every pull request. Editors can review the exact deployed version before merging.

Can I use React components from npm in Astro?

Yes. Astro supports React, Vue, Svelte, and others. You import components normally and add hydration directives when needed. But remember: every React component ships React’s runtime unless you keep it static.

What if my site outgrows static generation?

Migrate incrementally. Astro supports server-side rendering and API routes. You can make parts of the site dynamic without rewriting everything. Or migrate specific features to Next.js while keeping most pages in Astro.


Your turn: Look at your last project’s JavaScript bundle. How much of it is actually used on the page? What would happen if you removed React and shipped HTML?

Enjoying this? 👉 Tip a coffee and keep posts coming

Found this helpful?

Share it with your network

Jay McBride

Written by Jay McBride

Software engineer with 10+ years building production systems and mentoring developers. I write about the tradeoffs nobody mentions, the decisions that break at scale, and what actually matters when you ship. If you've already seen the AI summaries, you're in the right place.

Based on 10+ years building production systems and mentoring developers.

Support my work on Buy Me a Coffee

Recommended for You

5 min read

Why I Chose Hugo for My Blog (and Why You Might Want to Consider It Too)

Why Hugo Is My Go-To Blogging Platform for Speed, Security, and Simplicity

Read Article
6 min read

Vibe Coding Is Just Prompting with Better Guardrails

Why treating AI-generated code like untrusted third-party dependencies changes everything

Read Article