Client Boundaries

Keep the browser thin by default and choose hooks, islands, or WASM only when the capability actually requires it.

#hooks#islands#wasm#dom-ownership

Client Boundaries

The order of preference in Vango is:

  1. server-driven UI

  2. hook

  3. island

  4. WASM

That order is a correctness gradient, not an aesthetic preference.

Hooks

Hooks attach client behavior to server-owned DOM.

go
1Ul(
2	Hook("Sortable", map[string]any{
3		"handle": ".drag-handle",
4	}),
5	OnEventValidated("reorder", reorderValidator, func(e vango.HookEvent) {
6		from := e.Int("fromIndex")
7		to := e.Int("toIndex")
8		reorder(from, to)
9	}),
10)

Use hooks for:

  • drag and drop

  • focus traps

  • dropdown behavior

  • tooltips

  • high-frequency interaction polish

Hooks must not take structural ownership of the subtree.

Islands

Use islands when a client runtime must own the DOM subtree.

go
1Div(
2	JSIsland("rich-editor", map[string]any{
3		"content": content.Get(),
4	}),
5	OnIslandMessageValidated(validateEditorMessage, func(msg vango.IslandMessage) {
6		// handle validated message
7	}),
8)

Rules:

  • island props must encode to a JSON object

  • Vango does not patch inside the island boundary

  • communication is message-based

  • stable list identity is mandatory if islands appear inside dynamic lists

WASM boundaries

Use WASM when client-local execution is the actual point, usually for latency-sensitive or offline-capable behavior.

Rules largely mirror islands:

  • props encode to a JSON object

  • communication is message-based

  • use it only when a hook or island is not enough

Standard hook wrappers

Standard hook wrappers remain available, but the preferred authoring model is still the direct app-authoring surface in vango, setup, and el.

Validation is mandatory

Hook, island, and WASM payloads are untrusted input.

In non-dev mode, reachable client-boundary sinks must be validator-covered. Use one of the validator-supported patterns instead of accepting arbitrary payloads.

Ownership mistakes to avoid

Do not:

  • rewrite server-owned DOM after Vango boots

  • use inline scripts to repair mismatches

  • keep retrying client mutation until patches happen to line up

  • use a hook when a library really needs subtree ownership

Repeated reloads here are correctness failures, not a signal to add more reload logic.

Choosing the smallest boundary

  • stay server-driven if possible

  • use a hook for behavior on server-owned DOM

  • use an island when a client library must own structure

  • use WASM when local execution or offline behavior is the real requirement

If you are introducing persistence or deploy-sensitive state, continue to Persistence and Deploys.