Astro and Svelte: Why I Believe They're the Future of Web Development
I remember when building a website was simple. You opened a text editor, wrote HTML, linked some CSS, threw in a script tag if you needed it. It worked. No bundlers, no transpilers, no configuration ritual before you could render “Hello World.”
Then we decided that wasn’t enough.
The Over-Engineering Problem
Somewhere along the way, building for the web became unnecessarily complex. We started needing build pipelines to ship a landing page. React popularized component-based architecture, but with it came hooks, effects, dependency arrays, virtual DOM reconciliation. And other frameworks followed suit.
I’ve worked primarily with Vue throughout my career. I chose it because of its promise of simplicity — Evan You created it after working with Angular at Google, wanting something more approachable. And for a while, it delivered. Vue 2’s Options API was intuitive: data(), computed, methods, watch. Clean, organized, easy to reason about. I built projects with it. I advocated for it.
But then Vue 3 arrived with the Composition API, and I started watching the same pattern unfold. The framework I’d chosen because it was simpler than React was gradually becoming just as complex:
<script setup>
import { ref, computed, watchEffect } from 'vue';
const count = ref(0);
const title = computed(() => `Count: ${count.value}`);
watchEffect(() => {
document.title = title.value;
});
</script>
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="count++">
Increment
</button>
</div>
</template>
Not terrible. But look at what happened: ref(), .value everywhere, computed(), watchEffect(), defineProps, defineEmits… Vue started as the “simpler React” and gradually absorbed the same complexity it was designed to avoid. The Composition API is powerful, but it added a learning curve that the Options API never had.
I chose Vue over React because of simplicity, and now Vue was walking the same path. Frameworks that start simple inevitably grow complex as they try to cover every use case. React did it first. Vue followed. Angular was born complex.
That’s what led me to Astro and Svelte.
Most websites are fundamentally content sites — blogs, portfolios, documentation, marketing pages. Mostly static. A wall of text with some images, maybe a contact form or a search bar. And yet we ship hundreds of kilobytes of framework code to display content that hasn’t changed since the last build.
Astro: Back to the Origins
Astro changed how I think about this. When I first tried it, my reaction was immediate: oh. This is how it should work.
An Astro component:
---
const title = "Hello World";
const posts = await fetch('/api/posts').then(r => r.json());
---
<section>
<h1>{title}</h1>
<ul>
{posts.map(post => (
<li><a href={post.url}>{post.title}</a></li>
))}
</ul>
</section>
<style>
section { max-width: 800px; margin: 0 auto; }
</style>
The frontmatter (between the --- fences) runs at build time — it fetches data, imports components, processes whatever you need. The template below is HTML with expressions. Styles are scoped. No virtual DOM. No runtime. No useEffect. No dependency arrays. No client-side hydration by default.
The output? Pure static HTML. Zero JavaScript unless you explicitly ask for it.
Astro brings back the simplicity of writing HTML with a script tag, but with modern developer experience — TypeScript, component architecture, build-time data fetching, optimized output. No ref(), no .value, no useState. Just HTML.
Here’s the core idea: your website probably doesn’t need JavaScript. Not all of it. Most pages are content. Content doesn’t need a runtime. It needs HTML.
When you do need interactivity — a search bar, a nav menu, a theme toggle — Astro uses Islands Architecture. Instead of hydrating the entire page, you hydrate individual components:
---
import Header from '@/components/layout/Header.svelte';
import BlogSearch from '@/components/blog/StaticBlogSearch.svelte';
---
<!-- Hydrate immediately — navigation needs to work right away -->
<Header client:load lang="en" />
<!-- Hydrate when visible — search isn't needed until scrolled to -->
<BlogSearch client:visible posts={posts} />
<!-- Everything else? Zero JavaScript. Pure HTML. -->
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
You control exactly when and how each interactive piece loads:
client:load— Hydrate immediately (critical UI)client:visible— Hydrate when scrolled into viewclient:idle— Hydrate when the browser is idle
A page with 95% static content and one search component? Only the search component ships JavaScript. Everything else is zero-cost HTML. In a Vue or React app, even a mostly-static page ships the entire framework runtime — tens of kilobytes before you’ve written a line of your own code.
Svelte: The Perfect Companion
If Astro is the foundation, Svelte is its ideal partner. I’ve worked primarily with Vue throughout my career, and I love it. But Svelte is different. It feels like what Vue always wanted to be but couldn’t quite achieve because of its runtime architecture.
Here’s that same counter in Svelte:
<script>
let count = $state(0);
let title = $derived(`Count: ${count}`);
</script>
<svelte:head>
<title>{title}</title>
</svelte:head>
<p>Count: {count}</p>
<button onclick={() => count++}>
Increment
</button>
Compare this to the Vue version. No ref(). No .value. No computed(). No imports from the framework. You declare state with $state(), derived values with $derived(), and the compiler figures out the rest. It generates the minimal DOM update code at build time — no virtual DOM diffing at runtime.
The code reads almost like vanilla HTML with reactive sprinkles. State changes update the markup. No layers of abstraction. It’s what Vue’s Options API felt like — but without the limitations that led Vue to the Composition API.
Svelte 5 Runes
Svelte 5 introduced Runes — a signal-based reactivity system. The API is small:
$state()— Reactive state$derived()— Computed values$effect()— Side effects$props()— Component props
Here’s a real example — a search component. First, Vue 3:
<script setup>
import { ref, computed } from 'vue';
const props = defineProps(['posts', 'lang']);
const query = ref('');
const currentPage = ref(1);
const filtered = computed(() =>
query.value.length > 2
? props.posts.filter(p => p.title.toLowerCase().includes(query.value.toLowerCase()))
: props.posts
);
const paginated = computed(() =>
filtered.value.slice((currentPage.value - 1) * 12, currentPage.value * 12)
);
const totalPages = computed(() => Math.ceil(filtered.value.length / 12));
</script>
<template>
<input v-model="query" placeholder="Search posts..." />
<article v-for="post in paginated" :key="post.id">
<h3>{{ post.title }}</h3>
<p>{{ post.description }}</p>
</article>
<span>Page {{ currentPage }} of {{ totalPages }}</span>
</template>
Now Svelte:
<script>
let { posts, lang } = $props();
let query = $state('');
let currentPage = $state(1);
let filtered = $derived(
query.length > 2
? posts.filter(p => p.title.toLowerCase().includes(query.toLowerCase()))
: posts
);
let paginated = $derived(
filtered.slice((currentPage - 1) * 12, currentPage * 12)
);
let totalPages = $derived(Math.ceil(filtered.length / 12));
</script>
<input bind:value={query} placeholder="Search posts..." />
{#each paginated as post}
<article>
<h3>{post.title}</h3>
<p>{post.description}</p>
</article>
{/each}
<span>Page {currentPage} of {totalPages}</span>
The difference is obvious. Vue needs ref() for every state, .value to access it, computed() for derived values, defineProps for props. It works — I’ve written this exact component in Vue dozens of times — but there’s friction everywhere. The .value unwrapping alone is a constant source of bugs.
In Svelte, state is $state(). Derived values are $derived(). Props are destructured from $props(). No .value. No framework imports. The compiler tracks dependencies and generates minimal update code. Less ceremony, same result.
Compiled, Not Runtime
Svelte’s core innovation is that it’s a compiler, not a library. While Vue ships a runtime (~30KB min+gzip) that handles virtual DOM diffing and reactivity proxies in the browser, Svelte does all that at build time. The output is vanilla JavaScript that makes surgical DOM updates.
For an Astro site that already ships zero JavaScript by default, this matters. When you do need an interactive island, Svelte keeps it small. Components compile to 30-40% less JavaScript than equivalent Vue or React components.
Why They Work Together
Astro builds static HTML at build time. Svelte compiles to minimal JS at build time. Together, the static stuff costs nothing and the interactive bits ship barely anything. No hydration tax for content that never changes.
The syntax feels natural too. Astro uses a frontmatter + template pattern. Svelte uses a script + template pattern. Moving between them is seamless.
Here’s an example from my site — the blog search is a Svelte component inside an Astro page:
---
// Astro: runs at build time
import StaticBlogSearch from '@/components/blog/StaticBlogSearch.svelte';
import { getBlogPosts } from '@/lib/blog';
const posts = await getBlogPosts('en');
---
<!-- Svelte component hydrated only when visible -->
<StaticBlogSearch client:visible posts={posts} lang="en" />
Data fetching at build time in Astro. Interactive search at runtime in Svelte. Each framework does what it does best.
What the Surveys Say
Am I just a fanboy, or is the community actually moving this direction? I looked at the numbers.
The State of JS 2025 survey tells a clear story: Astro is #1 in satisfaction with a 39-point lead over Next.js. Svelte maintains an 88% retention rate. The survey called Astro a “dangerous competitor” to Next.js — and that was before the Cloudflare acquisition.
The 2024 edition was similar: Astro ranked #1 in interest, retention, and positivity among meta-frameworks. Two consecutive years at the top. That’s not a fluke.
GitHub Rising Stars 2025 tracked +7,200 stars for Astro, +4,600 for Svelte. Stack Overflow 2025 showed Svelte at 53.7% admired. The numbers all point the same way: people who try these tools keep using them.
I’m not going to pretend surveys are everything — they measure sentiment, not destiny. But when satisfaction, retention, and growth all trend up for two years straight, something real is happening.
Performance
Philosophy and surveys aside — does it actually perform?
Astro ships 90% less JavaScript than Next.js for equivalent static content. In a real-world comparison, a Next.js site bundled 180 KB of JavaScript for the same content Astro delivered with 18 KB. That’s not optimization — it’s a fundamentally different architecture.
Astro sites consistently hit Lighthouse Performance scores of 98-100 by default. Real-world migrations: WordPress to Astro sees scores jump from the 70s to 96+. LCP improvements from 3.2s to 1.6s. 60% of Astro sites achieve “Good” Core Web Vitals, compared to 38% for WordPress and Gatsby.
On my own site, xergioalex.com, the results are a bit absurd. This isn’t a simple landing page — it has a growing blog in two languages, client-side search, interactive timelines, image lightboxes, dark mode, bilingual routing, and dozens of Svelte components. And yet it achieves a perfect 100 in all four PageSpeed categories — Performance, Accessibility, Best Practices, and SEO — on both mobile and desktop:
Desktop — 100/100/100/100:
Mobile — 100/100/100/100:
Desktop: 0.3s FCP, 0.3s LCP, 0ms TBT, 0 CLS. Mobile: 0.9s FCP, 1.5s LCP, 0ms TBT. Getting a quadruple 100 on desktop is already good, but mobile — where Google’s throttling is aggressive — is where it gets hard. With Astro + Svelte, the architecture works with you. The defaults are already fast; you just avoid actively slowing things down.
If you want the full story — the CSS-only Typewriter, the WCAG AA audit, the hydration directive audit — I wrote a deep dive: The Road to 100: How I Achieved Perfect Lighthouse Scores on Every Category.
Performance matters because it directly impacts user experience, SEO rankings, accessibility on slow connections, and hosting costs. When a stack delivers these results by default, that’s a real advantage.
The Cloudflare Acquisition
In January 2026, Cloudflare acquired The Astro Technology Company. A company with a market cap exceeding $40 billion decided Astro was important enough to acquire.
What matters: Astro remains MIT-licensed, open-source, and platform-agnostic. You can still deploy anywhere. The team gets to focus on the framework instead of building a business around it. And there’s now institutional money backing the ecosystem — Webflow ($150K), Cloudflare ($150K), Mux, Netlify, Wix, and Sentry all contributing to the Astro Ecosystem Fund.
This isn’t a startup experiment anymore. Companies like Microsoft (Fluent 2 Design System), Google, Firebase (migrated their blog from Blogger to Astro), Trivago, Visa, NBC News, and Unilever use Astro in production. 87% of Astro users plan to keep using it — the highest retention intent among all SSGs surveyed.
My Experience: This Site Is the Proof
I didn’t just read about Astro and Svelte — I built my entire personal platform with them. XergioAleX.com has:
- A growing blog in two languages (English and Spanish)
- Full bilingual architecture — every page, every UI string, every post in both languages
- Client-side search powered by a static JSON index, lazy-loaded with
requestIdleCallback - Dozens of interactive Svelte components — navigation, search, lightbox, timelines
- Dark mode with system detection and localStorage persistence
- RSS feeds, sitemap, SEO optimization — all built-in with Astro
I’ve written about the full build process in Building XergioAleX.com. The short version: building with Astro + Svelte feels like the early web with modern superpowers. Components that look like HTML. TypeScript safety. Fast builds. And the leanest output I’ve ever shipped.
For the curious, the stack:
| Layer | Technology | Role |
|---|---|---|
| Framework | Astro 5.x | Static site generation, routing, Content Collections |
| Interactive UI | Svelte 5.x | Search, navigation, lightbox, timelines |
| Styling | Tailwind CSS 4.x | Utility-first CSS with dark mode |
| Content | Markdown/MDX | Blog posts with frontmatter validation |
| Type Safety | TypeScript 5.x | Type-safe development |
| Linting | Biome | Fast linter and formatter |
| Deployment | Cloudflare Pages | Global CDN, edge caching |
| Search | Fuse.js | Client-side fuzzy search, lazy-loaded |
Each choice reinforces the idea: the simplest tool that does the job. Biome instead of ESLint + Prettier. Tailwind instead of CSS-in-JS. Cloudflare Pages instead of a server.
When to Choose Something Else
I should be honest: Astro is not the right tool for every project.
It excels at content sites, mostly-static sites, performance-critical sites, and SEO-heavy sites. It’s not the natural choice for fully interactive SPAs — apps like Figma or Google Docs where 100% of the page is a live interactive canvas.
For real-time dashboards, I’d argue Astro still works — the sidebar, navigation, and page structure are static content, and the live charts are Svelte islands with WebSocket connections. For complex state, Svelte 5 runes plus nanostores handle more than you’d expect.
But for apps where interactivity dominates every screen — a full SaaS with dozens of complex views — Vue with Nuxt, React with Next.js, or SvelteKit are more natural fits. Those frameworks earned their place.
Most websites aren’t Figma though. Most are a mix of content and interactivity. For those — which represent the vast majority of what gets built — Astro and Svelte aren’t just competitive. They’re better.
Try It Yourself
If any of this resonated, build something small. A blog. A portfolio. A documentation site. You’ll feel the difference.
- Astro Documentation — Start here
- Svelte Documentation — The interactive tutorial is great
- State of JS 2025 — Full survey data
- Astro Year in Review 2025 — The growth story
- Cloudflare Acquires Astro — The acquisition
You’re looking at a real Astro + Svelte site right now. Check out Building XergioAleX.com for the full story.
Let’s keep building — but simpler.
Stay in the loop
Get notified when I publish something new. No spam, unsubscribe anytime.
No spam. Unsubscribe anytime.