Acumatica · Astro

Astro Islands Architecture

Astro's islands architecture ships static HTML by default and hydrates only the interactive pieces — the model behind why Astro sites are fast, and how the client directives control it.

John Kihiu12 min read

Astro's islands architecture is the framework's central idea: a page ships as static HTML by default, and interactive components are isolated "islands" that hydrate independently, each with its own JavaScript bundle. This is the opposite default from a typical SPA framework, where the whole page is client-rendered unless you opt out — in Astro you opt in to client-side JavaScript per component, and most of a typical content site ships zero JS for the parts that don't need it.

How hydration directives work

A component becomes an island by adding a client:* directive when you use it in a template. client:load hydrates immediately on page load, client:idle waits for the browser's idle callback, client:visible hydrates when the component scrolls into the viewport via an IntersectionObserver, and client:media hydrates only when a CSS media query matches — useful for a mobile-only nav toggle that a desktop visitor never needs to pay for. Without any directive, the component renders to static HTML at build time and ships no JavaScript at all.

ASTRO · COMPONENT USAGE
---
import SearchBox from '../components/SearchBox.jsx';
import Newsletter from '../components/Newsletter.jsx';
---

Post title

Why per-component hydration beats whole-page hydration

The performance case is straightforward: a blog post with a comment widget and a newsletter signup doesn't need the full weight of a client-side router or global hydration to render mostly-static prose. Each island loads independently, so a heavy interactive widget lower on the page doesn't block a lighter one higher up, and a visitor who never scrolls to the newsletter form never downloads its JavaScript. This is the mechanism behind Astro's default low JavaScript footprint compared to frameworks that hydrate the entire page tree.

Islands don't share client-side state by default

Because each island hydrates independently, two islands on the same page do not automatically share state the way sibling components in a single SPA tree would. Cross-island communication needs an explicit mechanism — nanostores is the common choice in the Astro ecosystem — rather than React context or a shared store that assumes one hydration tree.

Framework-agnostic by design

Islands can be written in React, Vue, Svelte, Solid, Preact, or plain Astro components, and different islands on the same page can use different frameworks — each ships only its own runtime. This matters for incremental migration: a team moving off an older stack can introduce Astro pages that keep existing React components as islands while the surrounding page shell is plain Astro, without a full rewrite.

Choosing the right directive for a component

The directive choice is a judgment call about how soon a component needs to be interactive. Navigation and above-the-fold interactive elements usually warrant client:load. Anything below the fold — comment sections, related-content widgets, footers with interactive elements — is a good fit for client:visible, since it defers the JavaScript cost until the user is actually about to see it. client:only="react" skips server rendering entirely, useful for components that depend on browser-only APIs and would error during the server render pass.

client:only skips the static HTML fallback

A component using client:only renders nothing until JavaScript executes — there is no server-rendered placeholder. For anything above the fold or important for SEO, prefer a directive that still produces server-rendered HTML, and reserve client:only for genuinely browser-dependent widgets like a canvas-based chart.

DirectiveWhen it hydrates
client:loadImmediately on page load
client:idleAfter the main thread is idle
client:visibleWhen scrolled into the viewport
client:mediaWhen a CSS media query matches
client:onlyClient-rendered only, no SSR pass

Wrapping up

Islands architecture is worth adopting when most of a page's content is genuinely static and only a handful of components need interactivity — the default of zero JS unless you opt in is what keeps Astro sites fast without manual code-splitting. Pick the least eager hydration directive that still meets the UX requirement, and treat cross-island state sharing as something you build deliberately rather than something the framework gives you for free.

John Kihiu
Acumatica ERP Developer · Laravel Engineer

Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.