Islands Architecture, Explained
22 Oct 2026Islands architecture means shipping static HTML for the whole page and hydrating only the specific components that need JavaScript. The rest of the page — nav, footer, article text — stays plain HTML with zero JS attached. You get an interactive page without shipping a framework runtime for content that never changes.
The problem it solves
A typical SPA ships one JS bundle that hydrates the entire page, whether or not most of it is interactive. A blog post with a single comment widget and a single “like” button still downloads and hydrates React (or your framework of choice) for the whole page — including the paragraph text that will never change.
Islands flip that: the page is static by default, and you opt individual components into interactivity.
What it looks like in practice
Frameworks like Astro, and partial-hydration support in others, let you mark a component as an island explicitly:
---
import LikeButton from '../components/LikeButton.jsx';
---
<article>
<h1>Post title</h1>
<p>Static content, no JS shipped for this part.</p>
<LikeButton client:visible />
</article>
client:visible means: don’t hydrate until this component scrolls into view. Other common directives:
client:load— hydrate immediately on page load.client:idle— hydrate once the browser is idle (after more important work finishes).client:visible— hydrate on intersection with the viewport, good for below-the-fold widgets.
Everything without a client:* directive renders to static HTML and ships zero JS.
What you get
- Smaller JS payloads. You only pay JS cost for the components that need it, not the whole page.
- Faster first paint. Static HTML renders immediately; there’s no wait for a framework runtime to boot before the page looks complete.
- Framework flexibility. Different islands can use different frameworks on the same page in some implementations (a React island next to a Svelte island), since each hydrates independently.
What you give up
- Shared state across islands is harder. Two islands don’t share a component tree, so passing state between them means reaching for something explicit — URL params, a small shared store, or custom events — instead of just lifting state up like you would in a single SPA.
- Not every app fits this model. Highly interactive apps where most of the page is dynamic (a spreadsheet, a design tool, a chat app) don’t benefit — you’d end up making the whole page one big island, which is just an SPA with extra steps.
- More moving pieces to reason about. Knowing which components are static and which are islands is a design decision you have to keep making correctly. Slapping
client:loadon everything defeats the purpose and gets you back to shipping a full framework bundle.
When to reach for it
Content-heavy sites with a few interactive widgets — blogs, marketing sites, docs with a search box or theme toggle, e-commerce product pages with one “add to cart” button. If your page is mostly static prose with a couple of small interactive spots, islands architecture ships noticeably less JavaScript than a full SPA for the same result. If your page is an application from top to bottom, this isn’t the model you’re looking for — build it as a normal SPA.