Islands
@sigx/ssr-islands adds islands architecture to SignalX SSR: ship a static, server-rendered page and hydrate only the interactive components, each on its own schedule, with optional per-island code splitting.
It is the first-party reference strategy pack built entirely on the pluggable
@sigx/server-renderer plugin API —
not baked into core. The base renderer is strategy-agnostic; islands is just an
SSRPlugin registered on top (installed automatically as a dependency). The base
renderer hydrates the whole tree; islands lets you hydrate just the parts marked
with client:* directives — everything else stays as cheap static HTML. Because it
ships against the same public hooks, a third party can author their own strategy
pack the same way.
It ships from the core monorepo (signalxjs/core, packages/ssr-islands) and is
released in lockstep with @sigx/server-renderer.
Why islands
Most pages are mostly static. Hydrating the entire tree ships and runs JavaScript for content that never changes. With islands you opt in to interactivity per component:
- A
client:visiblechart hydrates only when scrolled into view. - A
client:idlewidget waits for the browser to be idle. - The surrounding article ships zero client JS.
The three pieces
Using islands always involves the same trio (from the package's own quick-start):
// 1. Server — install the pack on your app
import { createSSR } from '@sigx/server-renderer';
import { islandsPlugin } from '@sigx/ssr-islands';
import { defineApp } from 'sigx';
const app = defineApp(<App />).use(islandsPlugin());
const html = await createSSR().render(app);
// 2. Client — register island components, then hydrate them
import { hydrateIslands, registerComponent } from '@sigx/ssr-islands';
import { Counter } from './components/Counter';
registerComponent('Counter', Counter);
hydrateIslands();
// 3. JSX types — enable the client:* attributes
import '@sigx/ssr-islands/jsx';
<Counter client:visible />
<Widget client:idle />
The server plugin maps each client:* directive onto a core
boundary record, captures the
component's signal state, and injects the window.__SIGX_BOUNDARIES__ hydration
table. On the client, hydrateIslands() reads that table and schedules each island
according to its strategy.
Hydration strategies
| Directive | Hydrates… |
|---|---|
client:load | immediately on page load |
client:idle | during browser idle time (requestIdleCallback) |
client:visible | when the element scrolls into view (IntersectionObserver) |
client:media | when a media query matches (client:media="(min-width: 768px)") |
client:only | skip SSR entirely — empty placeholder on the server, mount fresh on the client |
See Client directives for the details of each.
Next steps
- Installation — install, dependency, and the four subpaths.
- Client directives — the five
client:*strategies. - Registry & code splitting — register components eagerly or lazily for per-island chunks.
- Plugin setup —
islandsPlugin()options, manifests, and signal-state transfer. - API reference — every export with signatures.
