Islands
Islands — hydration wrappers, registry, and dataflow helpers for Bastion WASM islands.
Islands are interactive WASM components hydrated on the client. Each island wrapper div carries: data-march-island — module name data-march-hydrate — when to load the WASM module (see HydrateOn) data-march-dataflow — "client" | "server" (see DataflowMode) data-march-state — initial state JSON data-march-island-css — optional scoped CSS (injected into <head> on hydration) data-march-channel — optional channel topic (Client mode, last-write-wins sync) data-march-parent — parent island instance ID (child islands only) data-march-on-event — event handler name on parent (child islands only)
Dataflow modes (spec: specs/islands-data-flow.md):
Client — island owns its own state, handles events locally via WASM.
Optionally syncs to a channel topic (last-write-wins).
No channel = purely local state.
Server — server owns state, client is a read-only projection.
The JS runtime does NOT attach event listeners.
State arrives only via the wired channel.Parent-child binding:
Child islands carry data-march-parent (parent instance ID) and
data-march-on-event (handler name). Children dispatch events upward
through the JS runtime's tree-walk. There is no global send bus.
Parents implement handle_child_event to receive dispatched events.Types
Interfaces
Functions
Generate the <script type="module"> tag that loads the island client runtime.
The runtime discovers data-march-island elements, opens the WebSocket, and
manages island lifecycle (hydration, event dispatch, DOM morphing).
Parameters:
base_url — URL prefix where island JS assets are served (e.g. "/_march/islands")Generate the <script type="module"> tag for the island runtime, with a CSP nonce attribute. Use this overload when Bastion.CSP is in the pipeline.
Parameters:
base_url — URL prefix for island JS assets
nonce — CSP nonce from BastionCSP.nonce(conn)
Example:
Islands.bootstrap_script_with_nonce("/_march/islands", BastionCSP.nonce(conn))Return the Client dataflow mode.
Client-only island placeholder: no server-rendered inner HTML.
The island div is present in the DOM for hydration, but the visible content
is entirely produced by the client-side WASM render function.Convert a DataFlow value to the data-march-dataflow attribute string.
Convert a dataflow mode value to the data-march-dataflow attribute string.
Accepts either DataflowMode (ServerOwned/ClientOwned) or DataFlow (Server/Client).Return the hydration strategy from a descriptor.
Return the module name from a descriptor.
Return the WASM file path from a descriptor.
Build a dispatch JSON message with source island info.
Return the Eager hydration strategy.
Get the event name from an IslandEvent.
Get the JSON payload from an IslandEvent.
Encode an IslandEvent as a JSON string.
Look up a registered island by module name.
Returns Some(Descriptor) if found, None otherwise.Return the channel topic from a FormConfig.
Return the redirect path from a FormConfig.
Convert a HydrateOn strategy to the data-march-hydrate attribute string.
Return the Lazy hydration strategy.
Construct an IslandEvent value.
Construct a FormConfig value.
Return the OnIdle hydration strategy.
Return the OnInteraction hydration strategy.
Return the OnVisible hydration strategy.
Generate a <link rel="modulepreload"> hint for a specific island's WASM file.
Tells the browser to start fetching the WASM file early, before the runtime
requests it. Include one per island that appears above the fold.
Parameters:
base_url — URL prefix for island assets
module_name — island module name (e.g. "Counter")Register an island descriptor in the registry.
Example:
Islands.empty_registry()
|> Islands.register(Descriptor("Counter", Eager, "/_bastion/islands/counter.wasm"))
|> Islands.register(Descriptor("TodoList", Lazy, "/_bastion/islands/todo_list.wasm"))Return the list of all registered island descriptors.
Generate a string of <link rel="modulepreload"> hints for all registered islands.
Returns an empty string if the registry is empty.Return the Server dataflow mode.
Validate that server-rendered HTML does not contain client event attributes.
Server islands are read-only projections. The compiler enforces this at
compile time, but this function provides a runtime check for tests and
dynamic render functions.
Returns Ok(html) if the HTML is clean, Err(message) if a forbidden attribute
is found. Forbidden attributes: data-on-click, data-on-input, data-on-change,
data-on-submit, data-on-keydown, data-msg.Validate that a render function's output for a given state does not contain client event attributes.
Calls render_fn(state_json) and runs validate_server_html on the result.
Returns Ok(html) or Err(message).Wrap server-rendered HTML with island metadata for client hydration.
Defaults to Client dataflow mode. No channel wired (purely local state).
Parameters:
name — island module name (e.g. "Counter")
strat — when to load the WASM module (HydrateOn)
state_json — initial state as JSON string
ssr_html — server-rendered inner HTML (shown before WASM loads)Wrap a child island slotted inside a parent island.
Children always have Server dataflow relative to their parent — they receive
props from the parent and dispatch events upward. The parent must implement
handle_child_event to receive those events.
Parameters:
name — child island module name
parent_id — parent island's instance ID
strat — hydration strategy
state_json — initial state JSON (derived from parent state)
css — scoped CSS (empty string = omit)
ssr_html — server-rendered inner HTMLWrap a child island with an explicit on_event handler name.
Use this when the parent registers a named event handler via on_event= in
its template. The on_event name must match what the parent's handle_child_event
is registered under.
Parameters:
name — child island module name
parent_id — parent island's instance ID
strat — hydration strategy
state_json — initial state JSON
css — scoped CSS (empty string = omit)
ssr_html — server-rendered inner HTML
on_event — event handler name registered on the parentWrap a child island with an explicit instance ID for unique identification.
Parameters:
name — child island module name
parent_id — parent island's instance ID
child_id — explicit instance ID for this child island
strat — hydration strategy
state_json — initial state JSON
css — scoped CSS (empty string = omit)
ssr_html — server-rendered inner HTMLConvenience: Client-mode eager wrap.
Convenience: Client-mode eager wrap with scoped CSS.
Wrap a form island with channel and redirect configuration.
Form islands have a built-in submit lifecycle:
1. User fills fields → UpdateField msgs update local state.
2. User submits → validate runs client-side.
3. If valid → push to channel topic.
4. Server responds → drive state to Success or show validation errors.
Parameters:
name — island module name
strat — hydration strategy
state_json — initial state as JSON string
form_html — server-rendered form HTML
channel_topic — channel topic for form submission (e.g. "contact:submit")
redirect — path to redirect to on success (e.g. "/thank-you")Convenience: Server-mode eager wrap (display-only island, no event listeners).
Wrap an island with a channel topic for state sync and an explicit dataflow mode.
When a channel is wired, the JS runtime pushes new state to the channel
topic after each local update (last-write-wins) for Client islands.
Server islands use the channel to receive server-pushed state.
Parameters:
name — island module name
strat — hydration strategy
mode — Client or Server dataflow mode
state_json — initial state as JSON string
css — scoped CSS (empty string = omit)
ssr_html — server-rendered inner HTML
channel_topic — topic string (e.g. "counter:#{user_id}")Wrap with island metadata including scoped CSS.
The CSS string is HTML-escaped and embedded in the data-march-island-css
attribute. The JS runtime creates a <style> tag in <head> on first hydration.
Parameters:
name — island module name
strat — hydration strategy
state_json — initial state as JSON string
css — scoped CSS (will be escaped for use in HTML attribute)
ssr_html — server-rendered inner HTMLWrap with an explicit DataflowMode and optional scoped CSS.
Parameters:
name — island module name
strat — hydration strategy
mode — Client or Server dataflow mode (DataflowMode or DataFlow)
state_json — initial state as JSON string
css — scoped CSS string (empty string = omit the attribute)
ssr_html — server-rendered inner HTML