Marketplace · Overlay Builder · Creator packages

Marketplace Creator & Overlay Widget Wiki

Choose the right package, build isolated visual widgets, create safe themes, carry over StreamElements custom widgets, and combine transparent creator bundles.

Current support: sheevchat-widget-v1 is active for isolated developer widgets, sheevchat-theme-v1 is active for presentation-only built-in themes, sheevchat-chat-game-v2 is active for declarative chat games, and StreamElements custom-widget imports retain their compatibility host. Community-pack recipes are not applied automatically yet.

SheevChat Overlay Widget Developer Wiki

Build visual packages for Overlay Builder without modifying SheevChat's native widgets. This reference explains which package type to use, what is supported today, how third-party code stays isolated, and how widgets, themes, action packs, and community bundles fit together.

SheevChat marketplace packages are small add-ons that teach SheevChat how to do more. Some connect SheevChat to another app, some add overlay widgets, some style widgets that already exist, and some bundle a complete setup. You do not edit SheevChat itself: describe the package in a manifest, include its files, and SheevChat decides where it can safely run.

Start Here: What Are You Making?

I want to...Build thisExample
Control another app from commands, automations, timers, or SheevPadaction_libraryChange a voice, mute a mixer channel, or trigger another app.
Turn events from another app into automation triggersaction_library with event subscriptionsRun actions when a local app emits an event.
Add a new visual to an overlaywidget_packA clock, spin wheel, goal bar, scoreboard, or avatar overlay.
Restyle a built-in SheevChat widgettheme_pack targeting a built-in widgetA neon Chat theme or compact Spotify card.
Restyle another creator's marketplace widgettheme_pack with a widget dependencyA pixel skin for an avatar widget.
Carry over a StreamElements custom widgetwidget_pack with provider: "streamelements"A purchased or self-made custom-widget export.
Add an installable declarative chat gamechat_gameA currency-free game, collection game, multiplayer session, vote, or package-defined economy.
Install several related pieces as one guided setupcommunity_packA widget, theme, and disabled-by-default recipes.

Streamer Or Theme Seller

If you have art, CSS, or a StreamElements widget, first decide whether you are changing an existing widget or adding new behavior. Use a theme for documented appearance settings. Use a widget pack when the package contains custom HTML or JavaScript. A StreamElements export should retain html.txt, css.txt, js.txt, fields.txt, and data.txt. Include useful previews, and never include secrets or customer data.

App Developer

Document how your app accepts commands and whether it emits events. Build an action library for its connection, actions, dynamic lists, authentication, and supported event subscriptions. Keep it declarative. If it also needs overlay output, publish that as a separate widget pack; a community pack can connect the pieces.

AI-Assisted Creator

Give the AI this wiki and the target app's authoritative API documentation. Require it to use only features marked available, report unsupported gaps instead of inventing fields, generate the appropriate manifest, and list what must be tested in SheevChat. A complete copyable prompt appears near the end of this page.

Choose The Correct Package

What you want to buildPackage typeUse when
New visual or runtime behaviorwidget_packThe overlay needs its own rendering, fields, events, assets, or saved state.
A new look for an existing widgettheme_packOnly documented appearance and theme-safe settings change.
App connections and callable controlsaction_libraryThe package talks to another app and exposes actions, sources, or triggers.
A restricted command-driven gamechat_gameSheevChat owns authoritative execution and state; optional visuals use a separate sandboxed companion widget.
A guided bundle of existing piecescommunity_packThe install combines dependencies and optional commands, automations, timers, or SheevPad recipes.

Do not use the deprecated overlay_pack type. Creators assemble layouts in Overlay Builder. Package behavior as a widget, appearance as a theme, and setup recipes as a community pack.

Hard Boundaries

  • Themes change appearance, not behavior.
  • Widgets add visual or runtime behavior.
  • Action packs connect to apps and expose actions, sources, and events.
  • Chat games declaratively register managed commands and compose only the resources, state, sessions, prompts, votes, and overlay events allowed by their runtime.
  • Community packs connect existing packages and recipes without hiding what will be installed.
  • Third-party widget code stays isolated from SheevChat's native widgets and main Overlay Builder document.
  • A widget pack must not add fields to, remove fields from, or change defaults for built-in widgets.
  • Normal Marketplace installs should not require end users to edit JSON manually.
  • Unknown provider values render as safe placeholders. They are never assumed to be StreamElements widgets.

Current Support Levels

LaneProviderStatusPurpose
StreamElements compatibilitystreamelementsSupportedCarry over purchased or self-made StreamElements custom widget exports in an isolated iframe.
First-party native renderersheevchatSheevChat-controlledNative marketplace widgets with a renderer maintained by SheevChat. Not a general third-party escape hatch.
Developer widget runtimesheevchat-widgetActive v1Developer-authored widgets run in an isolated iframe using the bounded window.SheevWidget API.
Missing or unknown providerany other valueMetadata onlyInstalls safely but renders a generic placeholder until a matching runtime exists.
Related package/runtime areaStatusNotes
Action libraries and imported actionsAvailableCommands, automations, timers, and SheevPad share the imported action registry.
Dynamic and cascading action fieldsAvailableSources may depend on earlier selections.
Local WebSocket, HTTP, TCP, UDP, MQTT, and approved IPCAvailable when declaredUse only documented bounded connection declarations.
Endpoint-file, instance-file, mDNS, and response discoveryAvailableIntended for dynamic ports, instances, and lists.
Bounded local event subscriptionsAvailableRemote/server webhook triggers are not available.
OAuth loopback/PKCE declarationsAvailable where supportedWebsite-relay requirements must be documented separately.
Response/query value ingestionAvailable for declared query actionsResponse maps, typed extraction, namespaces and sequence-scoped output variables are supported. See the Action Library wiki for exact fields, producer requirements and limits; this is not arbitrary persistent global state.
Built-in widget themesActive through sheevchat-theme-v1Themes may apply safe settings or use isolated HTML/CSS/JS presentation renderers. They cannot introduce app logic.
Community-pack dependenciesMetadata availableRecipe application is still pending; recipes must be visible and disabled by default.
Chat-game packagesActive through sheevchat-chat-game-v2Games can use managed commands, optional resources, random/prompt tables, scoped state, sessions, voting, and bounded companion-overlay events without arbitrary package code.
Paid packages, entitlements, ratings, and payoutsNot availableReserved metadata is not a working commerce system.

Use StreamElements compatibility for an actual StreamElements export. Use sheevchat-widget-v1 for new third-party widget behavior. If you only need to restyle a built-in SheevChat widget, use a theme pack and its sheevchat-theme-v1 presentation runtime.

Minimal Package Examples

Start with the smallest honest package, validate it, and expand only when the runtime needs more.

Minimal Built-In Theme

{
  "schemaVersion": 1,
  "id": "simple-chat-theme",
  "type": "theme_pack",
  "name": "Simple Chat Theme",
  "publisher": "Example Creator",
  "version": "1.0.0",
  "requires": [{ "type": "builtin_widget", "id": "chat", "required": true }],
  "themes": [{
    "id": "clean",
    "label": "Clean",
    "target": "chat_overlay",
    "settings": { "textColor": "#ffffff", "accentColor": "#8a6cff" }
  }]
}

Minimal Developer Widget Shape

This is the active v1 developer-widget shape:

{
  "schemaVersion": 1,
  "id": "simple-clock-widget",
  "type": "widget_pack",
  "name": "Simple Clock Widget",
  "publisher": "Example Creator",
  "version": "1.0.0",
  "compatibility": {
    "provider": "sheevchat-widget",
    "kind": "clock",
    "api": "sheevchat-widget-v1"
  },
  "capabilities": ["run_overlay_iframe"],
  "eventSubscriptions": ["chat.message", "widget.action"],
  "widget": {
    "files": {
      "html": "widget/index.html",
      "css": "widget/style.css",
      "js": "widget/widget.js"
    }
  },
  "fields": [{ "key": "textColor", "type": "colorpicker", "label": "Text color", "value": "#ffffff" }],
  "fieldData": { "textColor": "#ffffff" }
}

The HTML file is required. JavaScript and subscriptions are optional for static widgets; declare settings.staticWidget: true when the widget intentionally consumes no events.

Developer-widget fields[] entries use key, not id, to identify the corresponding fieldData value. A field includes key, type and a readable label; optional value supplies its fallback, with group, description, options, min, max and step used by the relevant control types. Inspector precedence is the placed widget's fieldDataOverrides, then package fieldData, then the field's value, then an empty value. Include intended runtime defaults in fieldData too: the iframe merges package fieldData with placed overrides; it does not derive defaults from fields[].value.

Minimal Community Bundle

{
  "schemaVersion": 1,
  "id": "simple-stream-setup",
  "type": "community_pack",
  "name": "Simple Stream Setup",
  "publisher": "Example Creator",
  "version": "1.0.0",
  "requires": [
    { "type": "widget_pack", "id": "simple-clock-widget", "required": true },
    { "type": "theme_pack", "id": "simple-clock-themes", "required": false }
  ],
  "recipes": [{
    "type": "automation",
    "name": "Show clock on stream start",
    "enabledByDefault": false
  }]
}

Minimal Chat Game Shape

Chat-game rules are JSON-only. The authoritative game runtime cannot execute JavaScript, SQL, shell commands, unrestricted expressions, filesystem access, or arbitrary request URLs. Optional presentation HTML/CSS/JavaScript may live in a separate widget_pack, or in explicitly referenced same-package widgets[] when the game declares overlay_widget. That code runs only in the isolated widget iframe. The active game runtime is sheevchat-chat-game-v2:

{
  "schemaVersion": 2,
  "id": "simple-die",
  "type": "chat_game",
  "name": "Simple Die",
  "publisher": "Example Creator",
  "version": "1.0.0",
  "runtime": "sheevchat-chat-game-v2",
  "capabilities": ["managed_commands", "weighted_random"],
  "managedCommandCategory": { "id": "simple-die", "name": "Simple Die", "deletionPolicy": "uninstall_only" },
  "resources": [],
  "state": [],
  "tables": {
    "die": [
      { "id": "one", "label": "1", "weight": 1, "value": 1 },
      { "id": "six", "label": "6", "weight": 1, "value": 6 }
    ]
  },
  "commands": [{
    "id": "roll",
    "trigger": "!rolldie",
    "aliases": ["!dice"],
    "arguments": [],
    "steps": [{ "op": "choose", "table": "die", "result": "roll" }],
    "response": "@{identity.username} rolled {result.roll.value}."
  }]
}

The runtime also supports package resources and inventory, cached host-approved prompt sources, scoped state, sessions and multiplayer, community contributions, voting, leaderboards, command fallbacks, streamer-managed aliases, transactions, and optional companion-overlay events. See the Chat Game Creator Wiki for the complete active boundary.

Same-Package Game Companion Example

To add a visual to the simple-die game above, merge these properties into that same manifest (this fragment is not a standalone manifest):

{
  "capabilities": ["managed_commands", "weighted_random", "overlay_events", "overlay_widget"],
  "compatibility": { "provider": "sheevchat-widget", "api": "sheevchat-widget-v1" },
  "overlay": { "events": ["rolled"] },
  "widgets": [{
    "id": "die-display",
    "label": "Die display",
    "files": { "html": "overlay/display.html", "js": "overlay/display.js" },
    "eventSubscriptions": ["game.simple-die.rolled"]
  }]
}

Append this step after the command's existing choose step:

{ "op": "emit_overlay", "id": "rolled", "payload": { "value": { "ref": "result.roll.value" } } }

Create overlay/display.html with <output id="roll">Waiting for a roll</output> and overlay/display.js with:

SheevWidget.on('game.simple-die.rolled', ({ event }) => {
  document.getElementById('roll').textContent = String(event.data.value);
});

Include both files in the package and select its Die display surface in Overlay Builder. The host chooses the result and publishes the committed event; the companion only displays it. This minimal event-only example does not hydrate a past roll on reload. Same-package companion subscriptions use game.<package-id>.<event-id>. Marketplace source releases also need normal icon/catalog metadata, matching declared capabilities and a compatible app minimum; 2.8.0 supports this example. Unreferenced game JavaScript is not a supported escape hatch. A separate companion package is also supported through the specialist game contract; do not give either arrangement authority to change game state.

Widget Pack Manifest

Non-action packages use a root-level manifest.json inside a .sheevpack or .zip package.

{
  "schemaVersion": 1,
  "id": "minimalist-glow-chat",
  "type": "widget_pack",
  "name": "Minimalist Glow Chat",
  "publisher": "Example Creator",
  "version": "1.0.0",
  "description": "An isolated custom chat widget for Overlay Builder.",
  "targets": ["overlay", "chat"],
  "tags": ["chat", "minimal", "glow"],
  "compatibilityTags": ["chat-widget", "streamelements-custom-widget"],
  "capabilities": ["run_overlay_iframe", "receive_sheevchat_events"],
  "requires": [],
  "compatibility": {
    "provider": "streamelements",
    "kind": "custom_widget",
    "api": "custom_widgets",
    "listeners": ["message", "follower-latest", "subscriber-latest"]
  }
}

Identity Rules

  • id uses lowercase letters, numbers, _, or -, is 3–80 characters, and starts and ends with a letter or number.
  • version uses semver-style text such as 1.0.0 or 1.1.0-beta.2.
  • type is widget_pack for new widget behavior.
  • targets are short discovery labels such as overlay, chat, spotify, game, or vtuber.
  • compatibilityTags are stable machine-friendly matching labels.
  • Keep the provider explicit.

Provider Lanes

StreamElements Compatibility

Use only for a StreamElements custom widget export:

{
  "compatibility": {
    "provider": "streamelements",
    "kind": "custom_widget",
    "api": "custom_widgets"
  }
}

SheevChat loads the original HTML, CSS, and JavaScript in a sandboxed iframe owned by the isolated Marketplace Item widget. It does not merge imported fields or behavior into Chat, Spotify, Giveaway, Credits, YouTube Media, Clip, Image, Text, or Alert Box.

First-Party SheevChat Widgets

provider: "sheevchat" is reserved for SheevChat-owned or tightly controlled native renderers. A native manifest can describe widgets and editable fields, but declaring this provider does not make arbitrary third-party code execute natively.

The desktop may own the renderer contract, but the widget manifest, defaults, previews, and themes still belong in an installed Marketplace package; first-party proof packages are not assumed to be bundled into the desktop app.

{
  "compatibility": {
    "provider": "sheevchat",
    "kind": "clock",
    "api": "native-clock-v1"
  },
  "widgets": [
    {
      "id": "clock",
      "label": "Clock",
      "kind": "clock",
      "entry": "widgets/clock.json"
    }
  ]
}

Developer Widget Runtime

The active developer lane uses provider: "sheevchat-widget" with api: "sheevchat-widget-v1". It runs package HTML, CSS, and JavaScript inside an isolated Marketplace Item iframe. SheevChat owns the websocket, event routing, state endpoint, asset/font requests, and audio requests; the iframe owns only its DOM and widget logic.

{
  "compatibility": {
    "provider": "sheevchat-widget",
    "kind": "spin-wheel",
    "api": "sheevchat-widget-v1"
  },
  "capabilities": [
    "run_overlay_iframe",
    "receive_sheevchat_events",
    "invoke_sheevchat_actions",
    "store_local_widget_state"
  ],
  "eventSubscriptions": ["chat.message", "event.follow", "widget.action"],
  "widget": {
    "files": {
      "html": "widget/index.html",
      "css": "widget/style.css",
      "js": "widget/widget.js"
    }
  }
}

The HTML entry is required and all runtime file references must exist inside the package. Missing JavaScript or subscriptions produce developer warnings rather than install errors because static widgets are valid. An unsupported API or an escaping/missing HTML path blocks installation.

The iframe exposes:

SheevWidget.apiVersion
SheevWidget.packageId
SheevWidget.title
SheevWidget.settings
SheevWidget.fieldData
SheevWidget.runtime()
SheevWidget.visible()
SheevWidget.on(type, handler)
SheevWidget.off(type, handler)
SheevWidget.ready()
SheevWidget.log(message)
SheevWidget.error(error)
SheevWidget.requestAsset(url)
SheevWidget.requestFont(href)
SheevWidget.playAudio(src, options)
SheevWidget.resize(width, height)
SheevWidget.setVisible(visible)
SheevWidget.getState()
SheevWidget.setState(state)

HTML/CSS support {{fieldName}} and safe {fieldName} substitution. Relative HTML and CSS assets are rewritten to guarded package-local routes; requestAsset("assets/logo.png") resolves dynamic assets. setVisible(false) hides the iframe surface without destroying it or clearing its state.

Common neutral subscriptions include chat.message, event.follow, event.sub, event.raid, event.cheer, event.superchat, event.twitch_ad_schedule, widget-button, and widget.action. chat, event, and * are broad aliases; avoid the noisy wildcard in production.

SheevWidget.on('init', () => SheevWidget.ready());

SheevWidget.on('chat.message', ({ event, replay }) => {
  renderMessage(event.user, event.message, event.platform);
});

SheevWidget.on('widget.action', ({ event }) => {
  runAction(event.field, event.data?.payload);
});

Interactive widgets may declare button fields. Overlay Builder clicks and the built-in Trigger Marketplace Widget action both deliver the field/action key through event.field; optional action JSON arrives at event.data.payload. The runtime also emits snapshot, visibilityChanged, settingsChanged, assetReady, fontReady, audioPlayback, and shutdown.

StreamElements Export Layout

SheevChat recognizes the classic custom-widget export:

widget.ini
html.txt
css.txt
js.txt
fields.txt
data.txt

Required files:

  • html.txt
  • css.txt
  • js.txt
  • fields.txt
  • data.txt

widget.ini is optional for detection but should be included when available. Relative HTML and CSS assets are rewritten to safe package-local routes at runtime.

Editable Fields

For StreamElements-compatible widgets:

  • data.txt supplies default fieldData.
  • fields.txt defines the controls shown in the Marketplace Item inspector.
  • Each placed widget stores its own fieldDataOverrides.
  • Runtime data is merged as defaults plus the placed widget's overrides before onWidgetLoad.
  • {{fieldName}} and safe {fieldName} template values are substituted from the merged fields.
  • Hidden fields remain hidden.
  • Field descriptions and help text should explain creator-facing effects.

Supported controls include toggles, dropdowns/selects, color pickers, text and multiline text, numbers/sliders, Google fonts, image/video/audio/media paths, hidden values, buttons, and grouped controls. button sends a widget action instead of storing a setting.

social_accounts stores repeatable { platform, username, url?, icon?, label?, logoStyle? } objects for social tickers and similar widgets. Packages may supply platformOptions and enable custom links with showLinkField: true or allowCustomLinks: true. Runtime code should ignore incomplete draft rows.

Runtime Isolation

StreamElements-compatible code runs inside a sandboxed iframe:

  • The widget cannot access the parent Overlay Builder DOM.
  • Built-in widgets never load the StreamElements runtime.
  • The parent owns the SheevChat websocket and distributes bounded event data to widget frames.
  • Widget frames should not open duplicate SheevChat websocket connections.
  • Relative package assets resolve through safe local marketplace routes.
  • Script errors and rejected promises are forwarded to the overlay console with package context.
  • Iframes persist during normal updates so animations do not restart for every message.

Use window.sheevchatResolveAsset(path) when compatible widget JavaScript must resolve a packaged asset dynamically.

Sandbox isolation does not mean all outbound browser networking is blocked. The developer-widget and StreamElements host CSP permits http:, https:, ws: and wss: connections; browser CORS and other browser policies still apply. These iframes receive no Electron or Node API, and cannot access the parent DOM. Use the parent-managed asset/font/audio services and shared event connection where provided; never put credentials in a visual package or open duplicate SheevChat/platform connections. Capability declarations are not an iframe network-host allowlist.

Events And Sample Data

The compatibility host supports onWidgetLoad, onEventReceived, and onSessionUpdate. Live chat is delivered with listener: "message". Common mapped event listener names include:

  • follower-latest
  • subscriber-latest
  • raid-latest
  • cheer-latest
  • superchat-latest
  • sponsor-latest
  • tip-latest
  • host-latest
  • redemption-latest
  • purchase-latest
  • merch-latest
  • charity-latest

Only declare listeners the widget actually consumes. Fields such as platform, provider, user id, display name, message, amount, count, currency, viewers, badges, and emotes are supplied when SheevChat has an equivalent value. Do not assume every platform supplies every field.

Overlay Builder provides sample chat and alert events for local testing. A widget should handle missing optional values and representative sample data without crashing.

Local Widget State

Developer Widget Persistence

SheevWidget.getState() and SheevWidget.setState(state) are asynchronous. The returned envelope is { store, counters, updatedAt }: use store for JSON-safe widget data and counters for numeric values. updatedAt is generated during host normalization, including reads; it is not a durable last-save revision. Arbitrary top-level properties are discarded; setState({ score: 7 }) does not save score.

For an explicit, intentional save (call once when that user/widget action occurs):

async function saveScore(score) {
  const current = await SheevWidget.getState();
  if (!current.store || !current.counters || !current.updatedAt) {
    throw new Error('Widget state could not be loaded; do not overwrite it.');
  }
  return await SheevWidget.setState({
    store: { ...current.store, score },
    counters: { ...current.counters }
  });
}

Each save replaces the package's entire state envelope; it is not a patch or atomic increment. All placements and browser sources using that installed package share it, so simultaneous read/modify/write calls can overwrite each other. Handle failures rather than resetting existing state: getState() logs read exceptions and returns {}; a response without state also returns {}. setState() rejects on a failed save and returns the host-normalized saved state on success. Do not save on every redraw, replay or initialization.

Host sanitization limits are 200 keys per object and counter map, keys truncated to 120 characters, strings truncated to 4,000 characters, arrays truncated to 100 items, and nested arrays/objects at depth 6 replaced with null (the store root starts at depth 0). Use finite numbers: JSON encoding can turn non-finite values into null; counters are normalized to finite numbers, with invalid values becoming zero. The total serialized state is capped at 256 KiB; an oversized save fails. Use plain JSON data and inspect the returned normalized value when limits matter.

SheevTheme.getState() is different: it synchronously returns the current theme render snapshot. It is not persistent storage and has no matching theme setState() API.

StreamElements Compatibility State

StreamElements-compatible widgets can use bounded SE_API.store and SE_API.counters shims.

  • State is scoped to the installed package id, not each canvas instance.
  • Store values must be JSON-safe.
  • Use plain JSON data. Functions, DOM nodes, symbols, cycles and class instances are not a supported representation: serialization may omit, coerce or reject them, and cannot preserve prototypes or object identity.
  • Keys, strings, nesting depth, and total state size are capped.
  • Persistence failures fall back to memory for the current page load and are logged.
  • Store and counter changes emit compatibility update events.

Do not use widget state as a secret store. Do not place credentials or platform tokens in fields, assets, or persisted widget state.

Assets And Previews

Bundle runtime assets whenever possible. Package file references must be relative and remain inside the package. Do not use .., absolute paths, or drive letters.

{
  "previews": [
    { "file": "previews/card.png", "label": "Marketplace card", "type": "image" },
    { "file": "previews/demo.mp4", "label": "OBS preview", "type": "video" }
  ]
}

Catalog preview URLs must use HTTPS. Bundled previews are useful after download; catalog-hosted previews are preferred for marketplace browsing.

Marketplace and Installed Apps cards now display catalog previewUrls and explicitly listed bundled previews[]. Installed preview files are served only when the manifest lists them. Package details also show trust, capabilities, provider/kind/API, dependencies, tags, compatibility tags, release notes, package id/version, minimum SheevChat version, and install/update state. Missing required dependencies can link to their Marketplace install action when available.

Useful catalog/manifest metadata:

{
  "publisherId": "example-creator",
  "trust": "verified_creator",
  "capabilities": ["run_overlay_iframe", "receive_sheevchat_events"],
  "previewUrls": ["https://marketplace.sheevchat.com/previews/example.png"],
  "changelog": "Initial Marketplace release."
}

Theme Packs

A theme changes presentation, not application behavior. It may apply documented theme-safe settings or provide isolated presentation HTML/CSS/JavaScript through sheevchat-theme-v1. SheevChat still owns connections, filtering, emotes, queues, actions, and source state. Themes must not add app connections, moderation, command parsing, queue rules, or hidden automations. The optional beta.82+ viewer_choices declaration below lets the host supply managed choice commands and saved public selections; it does not give the iframe command-processing authority.

Theme A Built-In Widget

{
  "id": "neon-glow-chat",
  "type": "theme_pack",
  "name": "Neon Glow Chat",
  "version": "1.0.0",
  "requires": [
    { "type": "builtin_widget", "id": "chat", "required": true }
  ],
  "themes": [{
    "id": "neon",
    "label": "Neon",
    "target": "chat_overlay",
    "renderer": {
      "api": "sheevchat-theme-v1",
      "html": "themes/neon/index.html",
      "css": "themes/neon/style.css",
      "js": "themes/neon/theme.js"
    },
    "settings": { "textColor": "#ffffff", "accentColor": "#8a6cff" },
    "frame": { "width": 760, "height": 600 }
  }]
}

Stable dependency ids include chat, spotify, giveaway, credits, youtube_media, clip, image, text, and alert_box. Renderer targets are chat_overlay, spotify_overlay, giveaway_overlay, credits_overlay, youtube_media_overlay, clip_overlay, image, text, and alert_box.

At least one renderer file should exist; HTML is recommended. Renderer files and their asset references must remain package-local. The iframe receives settings, frame, and target-specific data through postMessage.

SheevTheme.on('init', ({ settings, data, frame }) => {
  render(settings, data, frame);
  SheevTheme.ready();
});

SheevTheme.on('update', ({ settings, data, frame }) => {
  render(settings, data, frame);
});

The active API provides on, ready, log, error, requestAsset, requestFont, playAudio, setVisible, and getState, plus package, theme, target, and API identifiers. Runtime messages include init, update, visibilityChanged, assetReady, fontReady, audioPlayback, and shutdown.

Built-In Theme Data Contracts

TargetCurrent data
spotify_overlayspotify_overlay_v1: track aliases, playback state, artwork, normalized progress, timestamps, and fallback palette.
chat_overlaychat_overlay_v1: visible/recent messages, events, combined feed, viewer presence/groups, emotes, badges, filters, and counts; optional package-scoped user.selections / viewerChoices through beta.82+ viewer_choices_v1.
giveaway_overlayAll, active, and visible giveaways.
credits_overlayCredits entries, visible credits, and roll state.
youtube_media_overlayCurrent item, queue, pending items, and playback position.
clip_overlayCurrent clip and queue.
image, text, alert_boxSettings, frame, and preview/static data only. Public event-driven alert data is still evolving.

Spotify themes should use hasTrack, hasArt, and hasDuration guards; use progress.percent for 0–100 bars and progress.ratio for 0–1 math. For ticking time, advance the numeric progress from progress.sampledAt while playing and clamp it to the duration. Do not open Spotify connections. Use the supplied palette when artwork color extraction fails, and keep the renderer responsive inside the manifest's natural frame.

Chat themes should use messages for chat, events for activity, feed for a combined timestamp-sorted display, and viewers or viewerGroups for presence. Rows include normalized platform, user, message/event, badges, roles, and timestamps. SheevChat applies platform and hidden-account filters before sending visible data; themes must not recreate moderation logic or open chat sockets.

Viewer Choices And Included Theme Commands

Available in SheevChat 2.8.0-beta.82 and newer: a native chat theme_pack can declare the generic viewer_choices capability with the additive viewer_choices_v1 contract. Viewers can select a cosmetic class, faction, avatar, team, or another package-defined option. This capability is available to third-party creators as well as SheevChat themes. It does not expand chat_game, StreamElements compatibility, or the Marketplace Item provider APIs.

SheevChat owns command registration, permissions, cooldowns, identity, persistence and updates. The theme only renders the host-supplied choice. Never parse commands in the iframe or add sockets, network polling, profile writes or hidden automations for this feature.

Add this declaration to the theme manifest alongside its normal themes, renderer files and dependencies:

{
  "type": "theme_pack",
  "capabilities": ["run_overlay_iframe", "viewer_choices"],
  "viewerChoices": {
    "contract": "viewer_choices_v1",
    "choices": [{
      "key": "faction",
      "label": "Faction",
      "values": ["sun", "moon"],
      "command": "!factiontheme"
    }]
  }
}

Catalog marketplace.json must also declare viewer_choices in capabilities and set minSheevChatVersion to 2.8.0-beta.82 or newer. Publication validation rejects mismatched capabilities and an older minimum. Existing themes without this capability continue using chat_overlay_v1 unchanged.

The declaration is bounded and declarative:

  • 1–8 choices per package, each with a unique key and a 1–80-character label.
  • 1–1000 distinct allowed values per choice; keys/values match [a-z][a-z0-9_-]{0,39}.
  • One unique single-word !command per choice (maximum 80 characters), using letters, numbers, hyphens or underscores after !.
  • random and reset are reserved values. Arbitrary code, request URLs, scripts and target-viewer arguments are not supported.

Expanded capacity requires SheevChat 2.9.0-beta.7 or newer. Released 2.8.0 supports at most 32 values per choice. A package with any 33–1000-value declaration must set catalog minSheevChatVersion to 2.9.0-beta.7 or newer; publication and app catalog-install validation reject a lower minimum. Local imports require a supporting app. Existing 1–32-value packages and saved choices remain compatible, with no migration and the same viewer_choices_v1 contract name.

Viewer-choice help, invalid-input and confirmation responses use one chat message. The host automatically truncates overlength text with …, including the username prefix and marker in the limit; it does not reject a valid choice or send additional chunks. It keeps whole grapheme clusters and uses conservative UTF-16 limits of 500 for Twitch, 200 for YouTube and 150 for the current TikTok sender; Kick permits 500 graphemes and 2048 UTF-8 bytes. X applies local choices silently. These bounds apply to viewer-choice replies; other command families keep their existing behavior. Provide a full option list in package help or a companion UI when a long list will not fit in chat.

The host installs the command under Bot Commands → Installed Command Packs. Streamers get the standard enable switch, platform toggles, authority, per-viewer/global cooldown, command rename/reset and alias controls. Commands are initially enabled. SheevChat commands take priority, followed by custom commands, then Marketplace commands; an occupied trigger receives a stable alternative shown on its command card. Package command declarations are not permission to change existing commands.

With the example above, !factiontheme moon selects Moon; !factiontheme reports the saved selection and usage; !factiontheme random or !factiontheme reset clears it. Values are case-insensitive. Invalid values or extra arguments produce usage without changing data. Commands change only the calling viewer's value. Twitch, YouTube, Kick, TikTok and X use their configured platform/permission gates; X applies local choices while chat responses remain silently suppressed. Existing chat-game platform capabilities remain unchanged.

Read Choices In A Renderer

For normalized chat and viewer rows, the active package receives an optional object at row.user.selections:

function renderChat(data) {
  for (const message of data.messages || []) {
    const faction = message.user?.selections?.faction;
    const appearance = faction === 'sun' ? 'sun' : faction === 'moon' ? 'moon' : 'neutral';
    renderMessage(message, appearance); // Your package's presentation function.
  }
}

SheevTheme.on('init', ({ data }) => { renderChat(data); SheevTheme.ready(); });
SheevTheme.on('update', ({ data }) => renderChat(data));

The parent also supplies a scoped summary:

{
  "viewerChoices": {
    "contract": "viewer_choices_v1",
    "packageId": "your-theme-package",
    "definitions": [{"key":"faction","label":"Faction","values":["sun","moon"],"command":"!factiontheme"}],
    "viewers": [{"platform":"x","userId":"example-id","username":"viewer","selections":{"faction":"moon"}}]
  }
}

Only the active theme package's choices are projected into its iframe, for rows present in the supplied chat/viewer data, including bounded recent history. A theme does not receive sibling-package choices or private viewer notes through this capability. messages remains filtered by the parent; do not use allMessages to bypass its platform or hidden-account filtering.

The host hydrates choices on connection and sends normal theme update payloads after a change/reset. Re-render existing rows when their selections change; message ID alone is not a sufficient render-cache key. Do not reload the iframe to apply a choice. Treat absent or unknown values as a neutral/default/random visual fallback, and preserve any session-random fallback separately from explicit choices.

Identity, Persistence And Lifecycle

Saved selections are scoped to the installed package and the viewer's platform identity. Stable user IDs are preferred; username fallbacks follow the app's identity merge when an ID becomes available. Matching usernames on different platforms are separate viewers. Choices persist in local SQLite across app/source restarts and normal package updates, following normal database backup/restore. Disabling the command preserves saved choices. Reset clears the caller's choice; uninstall removes that package's saved choices and unregisters its commands. Values removed from a package's allowlist are omitted from public snapshots. Session-random defaults remain the renderer's memory-only behavior.

Working example: Tyrian Chat 1.1.0 declares profession with the nine base professions and !classtheme. !classtheme mesmer selects Mesmer, !classtheme inspects the choice, and !classtheme random restores the theme's session fallback. The app contains no profession-specific runtime logic.

Before publishing, validate the manifest/catalog version gate and test selection/query/invalid input/reset, repeated messages, independent viewers and platforms, source/app restart, already-visible row updates, standard command controls/conflicts and uninstall cleanup. Include an X local-selection case without expecting an outbound reply. Installed/OBS/live checks must be reported separately from automated fixtures.

Theme A Widget Pack

{
  "id": "stream-avatars-pixel-theme",
  "type": "theme_pack",
  "name": "Pixel Avatar Theme",
  "version": "1.0.0",
  "requires": [
    {
      "type": "widget_pack",
      "id": "stream-avatars-overlay",
      "version": ">=1.0.0",
      "required": true
    }
  ]
}

Third-party widget themes may change only the fields that widget declares themeable.

Dependencies

Dependencies are install-graph metadata. They do not execute code.

{
  "type": "action_library",
  "id": "stream-avatars-control",
  "version": ">=1.0.0",
  "required": false,
  "reason": "Enables avatar controls from SheevPad and automations."
}

Supported dependency types are action_library, widget_pack, theme_pack, community_pack, chat_game, and builtin_widget.

  • required: true means the package is not fully usable without the dependency.
  • required: false or optional: true describes a soft dependency.
  • Themes depend on the widget they style instead of bundling duplicate behavior.
  • Use semver/range text even while version enforcement remains informational in some surfaces.

Capabilities And Trust

Declare only capabilities the package uses. Relevant widget capabilities include:

  • run_overlay_iframe
  • store_local_widget_state
  • receive_sheevchat_events
  • invoke_sheevchat_actions
  • install_dependencies
  • add_disabled_recipes

Action-pack dependencies may separately request local WebSocket, HTTP, TCP, UDP, MQTT, IPC, OAuth, or endpoint-file access. A visual theme should normally request no runtime or network capability.

Treat capability names as declarations of intended use, not proof that every operation is independently permission-gated. In particular, declaring invoke_sheevchat_actions does not create an undocumented iframe action-execution method. Use the supported widget action/event lane and separate Action Library integrations. Publication validators reject unsupported schema fields/capabilities where that lane defines such checks; desktop widget metadata may preserve or ignore extra fields. Do not rely on an unknown field being rejected, and do not infer authority from it.

Public trust labels:

  • Official SheevChat
  • Verified Partner
  • Verified Creator
  • Marketplace Verified
  • Community
  • Local Import
  • Unverified

A community bundle inherits the lowest trust level among its dependencies.

Widget Plus Action Pack Pattern

Keep app control and overlay rendering separate:

  1. An action_library connects to the target app and exposes actions or events.
  2. A widget_pack renders the overlay and optionally depends on the action pack.
  3. A theme_pack changes declared visual fields.
  4. A community_pack installs the pieces and offers disabled-by-default recipes.

This structure lets users replace the theme without replacing behavior, use the control pack without the overlay, and understand every installed permission.

Developer Testing Checklist

  • The package id and version follow the identity rules.
  • manifest.json is at the package root.
  • The package type matches the behavior being added.
  • compatibility.provider names a supported lane.
  • Every capability is necessary and visible to the user.
  • Every required dependency exists and has a clear reason.
  • All file references are package-relative and traversal-safe.
  • The widget renders with sample data before OBS testing.
  • A sheevchat-widget-v1 package has an existing, package-local HTML entry and declares only the events it consumes.
  • An intentionally event-free developer widget declares settings.staticWidget: true or compatibility.static: true.
  • Widget actions handle both editor button clicks and the Trigger Marketplace Widget action without trusting payload JSON.
  • A sheevchat-theme-v1 renderer uses a documented target/data contract and never opens its own SheevChat or platform connection.
  • Missing optional event values do not crash the widget.
  • Multiple placed copies preserve independent field overrides.
  • Refreshing the overlay does not lose required bounded state.
  • Script failures appear with useful package context.
  • Themes modify only documented themeable fields.
  • Native SheevChat widgets remain unchanged after install.
  • Preview images or videos show the actual widget.
  • The changelog identifies compatibility or permission changes.

AI Prompt Template

Create, verify, correct, expand, and/or finish a SheevChat overlay widget package using the authoritative widget/API documentation supplied by the user.

Use the SheevChat Overlay Widget Developer Wiki:
https://sheevchat.com/overlay-widgets

First classify the deliverable:
- widget_pack for new visual/runtime behavior
- theme_pack for appearance-only changes
- action_library for app connections and callable controls
- community_pack for transparent dependencies and optional disabled recipes
- chat_game for declarative command games using `sheevchat-chat-game-v2`

Map the target documentation into SheevChat concepts before writing files. For an action library identify its connection, authentication, actions, fields, dynamic sources, event subscriptions, response ingestion, and capabilities. For a widget or theme identify its provider or target, editable fields, defaults, previews, dependencies, events, and capabilities. If the documentation requires unsupported behavior, put it in an "unsupported gaps" section instead of inventing schema or runtime APIs.

Hard rules:
- Do not use the deprecated overlay_pack type.
- Keep widget behavior, themes, app control, and recipes in separate package types.
- Never mutate SheevChat built-in widget fields or behavior from a third-party package.
- Use provider streamelements only for a real StreamElements custom-widget compatibility export.
- Use provider sheevchat only for a SheevChat-owned native renderer.
- Use only the documented `sheevchat-widget-v1` and `sheevchat-theme-v1` APIs; do not invent bridge methods or data fields.
- A `sheevchat-widget` package must include a valid package-local HTML entry. Declare only the subscriptions it consumes, or mark an intentionally event-free widget as static.
- A built-in theme renderer consumes parent-fed `settings`, `frame`, and `data`; it must not open SheevChat/platform sockets or take over app behavior.
- Route interactive widget buttons/actions through `widget-button` or `widget.action`; treat optional JSON as untrusted input.
- Declare only required capabilities and dependencies.
- Keep all package paths relative, traversal-safe, and inside the package.
- Chat-game rules use schema version 2 and contain no executable game logic. Optional presentation code may use a separate widget_pack or declared same-package widgets[] with overlay_widget and the isolated sheevchat-widget-v1 provider. Include only referenced companion files; the iframe cannot settle outcomes or mutate authoritative state.
- Never store secrets in fieldData, assets, widget state, or package metadata.
- Themes change only declared themeable fields and contain no hidden runtime behavior.
- Handle missing optional event values safely.
- Include useful preview metadata, version compatibility, and a changelog.

Before output, verify the package type, provider lane, required files, capability list, dependency graph, trust implications, asset paths, event listeners, editable fields, defaults, theme targets, sample-data behavior, and current runtime support.

Return the complete package file tree and the exact contents of every text manifest/source file. Include a short in-app test plan. Clearly label anything outside the active widget/theme v1 contracts or chat-game v2 contract as an unsupported gap.

Current Limitations

  • Arbitrary third-party JavaScript does not run inside native SheevChat widget renderers.
  • Unknown providers render safe placeholders.
  • sheevchat-widget-v1 is active, but future event names and bridge additions are not available until documented.
  • Imported StreamElements compatibility is bounded and does not guarantee every undocumented browser or platform behavior.
  • Widgets do not receive every field from every streaming platform.
  • Theme packs cannot change moderation, filtering, command processing, network behavior, or action execution.
  • Community recipes should be previewed and disabled by default until the user opts in.
  • Marketplace monetization and paid-theme rules remain outside this developer contract until legal and payment review is complete.
  • Paid checkout, entitlements, subscription gates, ratings, creator payouts, and creator-fund rankings are not active.
  • There is no public package upload/submission portal with automated review.
  • Remote webhook triggers that require SheevChat servers are not available.
  • SheevChat does not promise full StreamElements API parity or automatic native conversion of every imported widget.
  • Free local imports do not require a promised marketplace account system.
  • Third-party developers cannot bypass iframe isolation through a stable native renderer SDK.