SBCanvas API

The SBCanvas object is available globally inside every widget. Here’s the complete API.

Event System

SBCanvas.ready(() => {
  console.log('Runtime initialized');
});

SBCanvas.on('activity:follow', (activity) => {
  // low-level event bus access
});

SBCanvas.once('session:ready', (session) => {
  // fires once, auto-removes
});

// Fire callback after every 5th occurrence
SBCanvas.after('activity:subscribe', 5, (activity) => {
  SBCanvas.confetti();
});

// Emit custom events (prefixed with widget:)
SBCanvas.emit('combo-hit', { count: 10 });
// Other widgets receive via: SBCanvas.on('widget:combo-hit', handler)
MethodDescription
ready(fn)Run when runtime is initialized
on(event, fn)Subscribe to an event
once(event, fn)Subscribe once, auto-removes
off(event, fn)Unsubscribe a handler
after(event, count, fn)Fire after N occurrences
emit(eventName, data)Emit custom widget:{eventName} event

State

SBCanvas.state.goals         // current goal progress array
SBCanvas.state.chatMessages  // recent chat messages
SBCanvas.state.isConnected   // WebSocket connection status

SBCanvas.session             // frozen session data from backend
SBCanvas.version             // "0.1.0"

Fields

const fields = SBCanvas.getFieldData();          // active widget's fields
const other = SBCanvas.getFieldData('alert-box'); // specific widget's fields

SBCanvas.setField('color', '#ff0000');           // update + re-render
SBCanvas.setField('count', 5, false);            // update, skip re-render

const html = SBCanvas.injectFields('<p>{{message}}</p>', 'html');

Timers

const id = SBCanvas.setTimeout(() => hideAlert(), 5000);
const tickId = SBCanvas.setInterval(() => updateClock(), 1000);
SBCanvas.clearTimer(id);

Effects

SBCanvas.sound('/audio/ding.mp3', 0.8);
SBCanvas.animate(element, 'bounce');
SBCanvas.shake(element, 8);
SBCanvas.toast('Sub combo x5!', 3000);
SBCanvas.confetti({ count: 100, spread: 70 });

Queue Control

SBCanvas.holdQueue(30);   // pause alerts for 30 seconds
SBCanvas.resumeQueue();

Networking

const res = await SBCanvas.http('https://api.example.com/data', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: { key: 'value' }
});
// res = { ok: true, status_code: 200, body: {...} }

Channels

const ch = SBCanvas.channel('score');
ch.publish({ points: 42 });
ch.subscribe((data) => console.log(data.points));
ch.unsubscribe(handler);
ch.lastValue; // most recent publish

Sanitization

SBCanvas.sanitize.html('<script>alert("xss")</script>')
// "&lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;"
SBCanvas.sanitize.js(userInput)
SBCanvas.sanitize.url(userInput)
SBCanvas.sanitize.attr(userInput)

Status

const status = SBCanvas.getOverlayStatus();
// { connected, authenticated, width, height, scene, studio, debug, previewMode }

Namespaced APIs

NamespaceDescriptionPage
activitiesTyped activity stream (follow, sub, tip, etc.)
platformConnected platform info and feature detection
previewPreview mode and test event injection
bindReactive DOM data binding
mediaMedia preloading and playback sequences
serviceBackground service lifecycle
panelDashboard control panel
queueAlert queue inspection and control
chatSend messages to chat
emotesEmote resolution and sets
varsIn-memory runtime variables
storePersistent async key-value storage

Event Naming Convention

Activities can be listened to two ways:
// Activities API — cleaner, recommended for common use
SBCanvas.activities.on('follow', handler);
SBCanvas.activities.on('tip', handler);
SBCanvas.activities.on('*', handler); // wildcard: all activities

// Event bus — lower level, all event types
SBCanvas.on('activity:follow', handler);
SBCanvas.on('activity:tip', handler);
SBCanvas.on('activity:*', handler);
Both fire the same Activity object. Use activities.on() for readability. Use SBCanvas.on() when you need non-activity events like session:ready, chat:message, or store:update.