MultronHub

Understanding Astro's Island Architecture

Multron Team ·

What Are Islands?

In traditional SPAs, the entire page is a single JavaScript application. Every element — even static text — lives inside the framework’s component tree and requires JavaScript to render.

Astro flips this model. Pages are static HTML by default. Interactive components are opt-in “islands” that hydrate independently, each with its own framework runtime. Everything between the islands is plain HTML that renders instantly.

Think of it like an archipelago: islands of interactivity in a sea of static content.

Hydration Directives

Astro provides five client:* directives that control when an island hydrates:

DirectiveHydration TriggerBundle Impact
client:loadImmediately on page loadHighest — blocks nothing but adds to initial JS
client:idleAfter page load, when browser is idleMedium — deferred via requestIdleCallback
client:visibleWhen the element enters the viewportLow — lazy-loaded via IntersectionObserver
client:mediaWhen a CSS media query matchesConditional — only loads on matching viewports
client:onlyClient-side only, no SSRSpecial — skips server rendering entirely

Choosing the Right Directive

client:load — Immediately Interactive

Use for components that must work the instant the page appears:

<!-- Auth status in the header — users expect it immediately -->
<AuthStatus client:load />

<!-- A form that's above the fold -->
<SignInForm client:load />

When to use: Navigation elements, authentication UI, above-the-fold forms, anything the user will interact with in the first seconds.

client:idle — After the Page Settles

Use for secondary interactive elements that aren’t critical on first paint:

<!-- Newsletter signup in the sidebar -->
<NewsletterForm client:idle />

<!-- A "like" button below the article -->
<LikeButton client:idle />

The browser hydrates these during idle periods using requestIdleCallback. On busy pages, you can set a timeout fallback:

<NewsletterForm client:idle={{ timeout: 500 }} />

When to use: Secondary CTAs, non-critical interactive widgets, elements below the first viewport.

client:visible — Lazy Hydration

Use for components that live far down the page:

<!-- Comment section at the bottom of a long article -->
<CommentSection client:visible />

<!-- A heavy chart that's below the fold -->
<AnalyticsChart client:visible={{ rootMargin: '200px' }} />

The rootMargin option lets you start hydrating slightly before the element scrolls into view, avoiding a flash of inert content.

When to use: Below-the-fold content, comment sections, heavy visualizations, anything the user might never scroll to.

client:media — Responsive Hydration

Use for components that only make sense at certain viewport sizes:

<!-- Mobile hamburger menu — desktop shows a static nav -->
<MobileMenu client:media="(max-width: 768px)" />

When to use: Mobile-only menus, responsive widgets, viewport-dependent interactions.

client:only — Skip SSR

Use when a component cannot render on the server (e.g., it uses window, localStorage, or browser-only APIs):

<!-- This component reads from localStorage on mount -->
<UserPreferences client:only="react" />

Note: you must specify the framework name as a string argument.

When to use: Components with browser-only dependencies, third-party widgets that don’t support SSR.

Zero-JS Pages

The most powerful “directive” is no directive at all. Astro components without any client:* directive render as static HTML with zero JavaScript:

---
// This page ships ZERO JavaScript
import BaseLayout from '../layouts/BaseLayout.astro'
---
<BaseLayout title="About">
  <h1>About Multron</h1>
  <p>This page is pure HTML and CSS.</p>
</BaseLayout>

In Multron, the blog uses this approach. Every blog post renders to static HTML with syntax-highlighted code blocks — all at build time, all without client-side JavaScript.

Performance Impact

The difference is measurable. A typical React SPA might ship 80-150 KB of JavaScript before any content renders. An Astro page with islands ships only the JavaScript each island needs, and nothing for static content.

For Multron’s blog pages, that means:

  • 0 KB of framework JavaScript
  • Instant rendering — no hydration delay
  • Full interactivity on pages that need it, via targeted islands

This is the core insight of island architecture: most of the web is content, and content doesn’t need JavaScript.