# Castdeck template development — full reference A Castdeck template is a self-contained web page shown as an OBS Browser Source that reacts to live-stream comments and gifts via the CastdeckSDK. ## Load the SDK Runtime (OBS, running app): Development / reference: ## SDK API - setup(options?) — options = { port?: number = 3030, level?: "public" | "rich" }. Call before connect(). - connect() — Opens the comment stream (SSE /comments/events). Auto-reconnects every 3s. - disconnect() — Closes the stream. - subscribe(cb) — cb(ev: ProjectedEvent) is called for every event. Returns an unsubscribe function. - subscribeKind(kind, cb) — kind = "comment" | "gift" | "membership" | "follow" | "stats". Returns an unsubscribe function. - onSnapshot(cb) — cb(events[]) with the recent history on connect (up to 50). Returns an unsubscribe function. - getTierColor(tier) — Maps a gift tier (blue/teal/green/yellow/orange/magenta/red) to a CSS color string. ## ProjectedEvent fields - kind (public) — "comment" | "gift" | "membership" | "follow" | "stats" - platform (public) — "youtube" | "twitch" | "twitcasting" | "kick" | "nicolive" | "whowatch" - id (public) — Stable per-platform id. - timestamp (public) — Epoch milliseconds. - name (public) — Display name of the author. - message (public) — Comment text. - isMember / isModerator / isOwner (public) — Author role flags. - anonymous (public) — True for anonymous posters (Niconico 184 / Whowatch). - tier (public) — Gift color tier. - gift.displayText / gift.tier / gift.itemName (public) — Gift display info. - gift.amount / gift.currency / gift.jpyEstimate (rich) — Numeric gift amounts (require viewer consent). - membershipEvent / months (public / rich) — Membership event type / duration. - userId (rich) — Prefixed viewer id. - avatarUrl (rich) — Author avatar URL. - memberMonths (rich) — Membership months. - stats (public) — Viewer / like counters for stats events. public is the default projection level. rich fields require the streamer to grant consent; otherwise the stream is downgraded to public. ## Package format A template folder contains index.html (required) plus optional style.css, script.js, and castdeck-template.json: { "name": "My First Template", "author": "you", "version": "1.0.0", "kind": "display" } Packaging constraints (enforced on import): zip or .castdeck-template file; max 512 entries; max 50 MiB uncompressed; no symlinks or path traversal; a single wrapping folder inside the zip is unwrapped automatically. Imported templates get a trust tier: official | verified | local-unreviewed (manual imports are local-unreviewed and show a warning). Only kind "display" templates can be sold on the Castdeck store. ## Rules - No external network calls, CDNs, or analytics. Same-origin / inline only. - Escape user text before inserting into the DOM (XSS). - One overlay page, no build step. Do not include secrets. ## Minimal example
## AI context pack You are building a Castdeck overlay template. A template is a self-contained web page shown as an OBS Browser Source that reacts to live-stream comments and gifts. Follow these rules exactly. ## What you output Return: index.html (required), and optionally style.css, script.js, and castdeck-template.json (manifest: { "name", "author", "version", "kind": "display" }). Always set "kind": "display" — "function" templates cannot be sold on the Castdeck store. ## Runtime - Load the SDK: - Get events only via CastdeckSDK. Do NOT fetch any external URL, CDN, font, or analytics — the OBS page must not call third parties (privacy + security rule). - The SDK auto-reconnects; do not write your own reconnect loop. ## SDK API CastdeckSDK.setup({ port = 3030, level = "public" }).connect() // setup/connect return the SDK and may be chained const offAll = CastdeckSDK.subscribe(function (ev) { ... }) // every event; RETURNS an unsubscribe function — do NOT chain after subscribe const offKind = CastdeckSDK.subscribeKind("comment"|"gift"|"membership"|"follow"|"stats", function (ev) { ... }) const offSnap = CastdeckSDK.onSnapshot(function (events) { ... }) // recent history on connect CastdeckSDK.getTierColor(tier) // gift tier -> CSS color ## Event shape (ProjectedEvent), public level { kind, platform, id, timestamp, name, message, isMember, isModerator, isOwner, anonymous, tier, gift: { displayText, tier, itemName } } Rich fields (gift.amount, gift.currency, gift.jpyEstimate, userId, avatarUrl, memberMonths) require the streamer to grant rich consent. Build for the public level unless told otherwise. ## Rules - No external network calls, no CDNs, no analytics. Inline everything or use same-origin only. - Escape user text before inserting into the DOM (use textContent, or escape) to avoid XSS. - One overlay page, no build step. - Never include secrets or API keys. Now build the template I describe next.