Guide / 13 β€” Isomorphic Wasm

Wasm SDK

The github.com/ZiplEix/stewsdk/wasm package is automatically imported into every client Wasm bundle. It provides all the primitives for reactivity and DOM interactivity.

Low-level vs High-level SDK

The core wasm package (detailed below) provides the low-level foundation for Stew's client-side reactivity and DOM bindings.

For most use cases, it is easier and recommended to use the stew/* virtual packages (such as stew/ui, stew/io, or stew/nav). They provide a more idiomatic and higher-level API for interacting with the user and the browser DOM.

πŸ†˜ Having trouble?

Browser cache, TinyGo errors, or panics at startup.

Check Troubleshooting β†’

API Primitives (wasm.*)

wasm.BindContent(id string, ptr *string)

One-way Go β†’ DOM binding. Monitors the ptr pointer and updates the innerHTML of the element id on every mutation.

count := "0"
wasm.BindContent("counter-display", &count)
// Now if count = "42", the DOM will show "42" automatically

wasm.BindInput(id string, ptr *string)

Two-way Go ↔ DOM binding. Synchronizes an <input> HTML value with the Go variable in both directions (input ↔ program).

name := "World"
wasm.BindInput("name-input", &name)
// name is updated upon every keystroke in the input

state.New[T any](initial T) *Signal[T]

Creates a new Reactive Signal (in `stew/state`). Allows for precise tracking of the client app state for Auto-Tracking.

count := state.New(0)
username := state.New("Visitor")

state.Effect(cb func())

Registers a side effect (in `stew/state`). It executes immediately, detects which .Get() calls are made, and automatically re-executes only when one of those Signals mutates.

count := state.New(0)

state.Effect(func() {
    Console.Log("Counter:", count.Get()) // Executed only when count changes
})

wasm.OnClick(id string, handler func())

Shorthand for attaching a click listener to an element by its ID. Equivalent to OnEvent(id, "click", handler).

wasm.OnClick("my-button", func() {
    count++
})

wasm.OnEvent(id string, eventName string, handler func())

Attaches a listener for any DOM event on an element by its ID.

wasm.OnEvent("search-input", "input", func() {
    // Triggered on every keystroke in the input
})

wasm.OnEvent("form", "submit", func() {
    // Intercept form submission
})

wasm.GetPageDataJSON() string

Retrieves the stew.PageData JSON injected by the server in <script id="stew-pagedata">. Returns "{}" if missing.

rawJSON := wasm.GetPageDataJSON()
var state map[string]interface{}
json.Unmarshal([]byte(rawJSON), &state)

wasm.StartReactivityLoop()

Called automatically by the compiler at the end of each Wasm bundle. Keeps the main Wasm thread alive indefinitely (via select {}). Never call this manually.

Effect System β€” Internal Workings

The Signal system (Auto-Tracking) works with precise synchronization:

  1. Registration: When a state.Effect runs, it registers itself with the temporary global thread.
  2. Auto-Tracking: If a Signal.Get() is called during this thread, the Signal adds the effect to its exclusive list of subscribers.
  3. Propagation: When a Signal.Set() is triggered, it notifies the subscriber list to re-execute.

This cycle ensures that your application uses zero CPU resources when no state changes (Set) are induced.