codeLabs

When to reach for Svelte inside Astro

Astro & static sites · updated june 2026

astrosvelteislands

The islands architecture in Astro is genuinely good, and it’s also easy to misuse by reaching for a framework component out of habit rather than need. I’ve now got a rule I apply on every project: if the thing doesn’t hold state that changes after the page loads, it doesn’t get a Svelte component, full stop.

A pricing card, a testimonial grid, a footer with social links — none of that needs Svelte. It’s static markup, it renders once, and wrapping it in a framework component just adds a hydration boundary and a client bundle for something that was never going to update. I see this most often with cards and list items that get built as Svelte components purely because that’s what the developer reached for by default, and the result is dozens of tiny client islands hydrating on a page that has zero interactivity.

Where Svelte earns its place is actual state: a filter panel that updates a result list without a page reload, a multi-step form with validation and conditional fields, a cart that needs to reflect quantity changes instantly. Anything where a user action needs to change what’s rendered without a round trip. That’s the line — not “is this component complex” but “does this need to hold and react to state after the initial render.”

Svelte specifically, over React or Vue, because the compiled output is smaller and the runtime overhead per island is lower, which matters more in an islands architecture than in an SPA. You’re not paying one framework runtime cost once, you’re potentially paying it per island, so a lighter compile target adds up across a page with several interactive pieces.

The other habit worth building is hydration directive discipline. client:load hydrates immediately, which you want for something above the fold that needs to be interactive right away, like a nav toggle. client:visible defers hydration until the component scrolls into view, which is the right default for most interactive sections further down the page — a comment form or a related-content filter doesn’t need to hydrate before the user has scrolled anywhere near it. Using client:load everywhere out of not wanting to think about it defeats a decent chunk of what islands are for, because you end up front-loading JavaScript execution for things the user hasn’t reached yet.

The test I actually apply before writing a component: could I build this with a <details> element, a CSS :has() selector, or a native form, and skip JavaScript entirely? A surprising amount of “interactive” UI turns out to be expressible in plain HTML and CSS once you actually check, and that’s always the cheaper answer when it’s available.

Nic

builder, codelabs.com.au

Stay up to date with AI coding

New articles roughly every couple of weeks. No spam, unsubscribe any time.