Askr
Rendering

Client Rendering and Islands

Use client rendering and islands with the current published Askr packages.

  • @askrjs/askr0.0.59

How to use client rendering and islands

Keep the route tree shared and change the delivery adapter—not the component contract—when moving between client, server, and static rendering.

  1. Import the published @askrjs/askr entrypoint.
  2. Keep client rendering and islands configuration next to the component, route, or server composition root that owns it.
  3. Handle pending, unavailable, cancellation, and failure states, then verify the production path.
import { createSPA, hydrateSPA } from '@askrjs/askr/boot';

const root = document.getElementById('app')!;
if (root.childNodes.length) {
  await hydrateSPA({ root, registry });
} else {
  await createSPA({ root, registry });
}

SPA boot

`createSPA` from `@askrjs/askr/boot` mounts a fully client-rendered app into a root element and initializes the router from either a `manifest` (via `getManifest()`) or a plain `routes` array — manifest is the preferred, type-checked path. It accepts `auth`, `scrollRestoration`, and `cleanupStrict` alongside the route source, and returns a `Promise<void>` that resolves once the initial route has mounted.

Client boundaries

`hydrateSPA` is the counterpart used when the server already produced markup: it takes the same route source shape as `createSPA` plus a `hydrate` block (`verifyMarkup`, `deferUntilIdle`, `deferBelowFold`, `foldThreshold`, `skipSelectors`) that controls how aggressively hydration is deferred. Both functions live under `@askrjs/askr/boot`, keeping the split between "boot fresh" and "attach to existing DOM" as two distinct, narrow entry points rather than one flag-driven function.

Island ownership

`createIsland` enhances a single existing DOM node with one component and mounts once — no router involved. `createIslands` does the same for a list of `{ root, component }` pairs in one call and is described in the type as "the only public islands constructor," meaning multi-island pages should go through it rather than calling `createIsland` in a loop. Neither function touches routing state, so islands stay independent of whatever else is on the page.

When to choose client rendering

Pick `createSPA` when the whole page is interactive and there's no server response to enhance — dashboards, authenticated tools, anything behind a login wall where SEO and first-paint latency matter less. Pick islands (`createIsland`/`createIslands`) when most of the page is static content and only a widget or two needs `state()` and event handlers. If server-rendered markup already exists and needs to become interactive without a full remount, `hydrateSPA` is the right call instead of either.