StreamWizard.state stores a JSON blob per placed widget, so death counters
and sub goals survive OBS restarts and stream ends.
The API
get() returns your saved object or null; set() replaces it.
Spread the old state if you’re only changing one key.
A complete counter
Good to know
- Per placement: two copies of the same widget on different overlays have separate state.
- Editor preview has no state:
get/setthrow there, because the preview isn’t attached to an overlay. Wrap intry/catchor.catch()if you test in the editor a lot. - Don’t save on every frame: batch it. Save after a change settles, not inside an animation loop.
- Older widgets using
window.StreamWizard.stateUrlwith manualfetchstill work;state.get/setis the same API with the plumbing done.
Channel state: StreamWizard.userState
StreamWizard.state is private to one placed widget. StreamWizard.userState
is shared across the whole channel, stored key by key, and written by
StreamWizard’s servers too — which is the part that matters. A widget only
receives events while it is open, so anything you derive from an event is wrong
the moment the overlay was closed when it fired. Channel state is still there
when the widget comes back.
a-z, 0-9 or _. Values are any JSON up to 8KB,
and a channel can hold 200 keys.
Counters: use increment
Never build a counter with get then set — two writers racing (a mod
command and a widget, or two open overlays) lose updates. increment adds on
the server atomically and resolves to the new value:
delete(key)
removes a key entirely.
Live updates: subscribe
Every channel-state change — from this widget, another widget, StreamWizard’s
servers, or (soon) chat commands — is pushed to open overlays the moment it
lands. No polling:
subscribe(key, cb) and onChange(cb) (all keys, sys. included) both
return an unsubscribe function. Registering is safe anywhere — in the editor
preview there is no socket, so the callback simply never fires. The raw frame
also arrives as an onEventReceived with listener streamwizard.user_state
and event { key, value, updatedAt }, if you prefer one event handler.
Server-written keys
Keys beginningsys. are written by StreamWizard and are read-only — a widget
that could write them could lie about what the channel is doing.
This is how to react to something that happened while you were closed. Rather
than resetting a total on
stream.online — which does nothing if the overlay
opens later — record which stream the total belongs to and compare on load:

