ForgeCaster Creator Guide · v1.2.0
What you can build
Use Commands & Events in your workspace to build interactive experiences for your stream. Goals & random values are built in and use no add-on slots. Master Maker adds JavaScript logic, custom coded overlays and an editor for your own settings.
Master Maker starts at $20 per month for new monthly subscriptions, plus applicable tax, and inherits Master features. It includes three published add-on packages and three unpublished drafts. Existing subscriptions keep their agreed billing terms until a confirmed plan change. See the current Plans page and your Client Area for your price.
An add-on package may contain a minigame, several commands, events, state and its own overlay. A paused published package still occupies a slot. Archive it to free the slot. Archiving stops queued work; it keeps source and history until you delete the local copy. Lowering a plan limit does not erase existing packages. Bring the workspace under the new limit before publishing more changes.
Random chat values
Put these in a supported automatic chat, event reply, or message template:
{user}, your roll is {rng:1:20}.
{user}, you found {rng:1:8} treasure chests!
Both ends are included. {rng} uses the minimum and maximum from Commands & Events → Random values, initially 1 and 20. {rng:1:20} uses its explicit bounds. Write actual whole numbers in place of min and max; {rng:min:max} is an explanation of the format, not a literal usable token. Bounds may be between -1,000,000,000 and 1,000,000,000. Each occurrence rolls independently. Viewer text is inserted once and is never interpreted as another template or as code.
For a simple !roll command, create a chat event matching !roll, connect a chat action using the first example above, and choose its cooldown. This uses built-in chat templates and does not require a custom add-on.
Follow, Like, Gift and Custom goals
Open Overlays & Games → Goals to create, preview, style and copy each goal’s source link. Choose each platform and channel independently; your TikTok and Twitch usernames can differ.
- Open Overlays & Games → Goals and click Create goal.
- Name the goal and choose Follow, Like, Gift or Custom.
- Choose a platform and optional channel. A blank channel accepts matching events from that bot's configured channels. Choose All to combine platforms.
- Set starting value, current value and target. The target must exceed the starting value.
- For gifts, optionally filter by the exact gift name or ID. Gift value counts normalized coin/Bit value; Gift count counts completed gift units.
- Choose Manual, Daily in bot timezone, or New stream resets. New stream requires a single platform and channel.
- Adjust colors, dimensions, text, bar height and completion animation. Labels support
{name},{current},{target}and{percent}. - Save, then copy the overlay source link into TikTok LIVE Studio Link Source, or OBS/Streamlabs Browser Source. Use the configured width and height. The background is transparent.
A Custom goal moves through manual adjustments or a permitted add-on effect. The others use the bot's existing provider events; an overlay cannot discover events the provider does not deliver. Duplicate event IDs are not counted twice. A reset returns to the starting value. The progress bar stops visually at 100%, while the stored current value can continue to increase.
Keep source links private. Rotate a goal or custom overlay link to invalidate its previous copy. Browser sources cannot operate the bot. Goal displays contain only the selected goal's settings and progress.
TikTok room IDs and YouTube live-chat IDs identify new streams when available. For Twitch or a provider that does not supply a new session ID, use Start a new stream session on the configured channel. A reconnect to the same known stream does not reset stream goals automatically. Use one session per actual broadcast.
Create your first custom add-on
- Open Custom add-ons → Create add-on. The starter is a
!rollchat command. - Choose a unique slug, a name and an author credit. The slug is used in custom template values.
- Select only the permissions it needs. Choose subscribed events and optional commands/keywords. Commands must not overlap enabled built-in or custom commands.
- Paste JavaScript into Event handler, or load a
.jsfile. This is a function body, not a Node program. - Optionally supply HTML, CSS and browser JavaScript for the overlay. The editor can load these files as text. Loading and saving do not execute the new draft.
- Declare settings in Settings schema JSON, save, and use the generated settings boxes.
- Click Test simulated event. It uses an example viewer and empty private state, and reports proposed effects. It never spends points, changes live state, alters a queue or sends chat. When points permission is present, the simulated viewer has 1,000 points.
- Inspect the result, then Preview overlay if needed. A preview uses simulated display data and expires after 30 minutes.
- Publish reviewed draft after a successful test of that exact saved version and accept its declared permissions.
- For overlays, copy the published link to your streaming application's browser/link source.
Tests validate result structure and permissions. They do not guarantee that a real viewer will have enough points, a live queue will contain a request, or a chosen goal/redemption will exist. Test those conditions on a private stream before your show.
Saving edits does not replace the live version. Publication keeps up to 20 versions. Restore as draft, test and publish to roll back. Pausing immediately stops new work and prevents in-flight proposals from being applied. Three consecutive execution failures automatically pause a package. Check Execution history, fix the draft, test it and publish again.
JavaScript event contract
The handler receives ctx and api. Do not include export, import, a top-level await, or an outer function declaration. Return an ordinary JSON-compatible object. Promises are rejected.
const who = ctx.event.who;
const name = who?.display_name || who?.username || 'Viewer';
const roll = api.rng(1, ctx.settings.maximum);
return {
state: {last: roll, plays: (ctx.state.plays || 0) + 1},
values: {roll},
overlay: {text: name + ' rolled ' + roll},
effects: [{type: 'chat', text: name + ' rolled ' + roll}]
};
| Input | Meaning |
|---|---|
ctx.event |
Sanitized event: kind, key, platform, channel, who, text, value, at; provider events also include gift name and stream session. |
ctx.event.who |
Triggering viewer's platform identity and display name, or null for a timer/broadcast. Treat viewer text as untrusted display text. |
ctx.settings |
Validated values from this package's settings boxes. |
ctx.state |
This add-on's saved private JSON state, initially {}. |
ctx.viewer |
Triggering viewer's key and point balance when points permission is declared; otherwise null. |
ctx.viewers |
Up to 100 known viewers from your bot with keys, display names and balances, only with points permission. This is a bounded sample, not a full leaderboard or presence guarantee. |
ctx.goals |
This bot's custom goal IDs, names, current values and targets. |
ctx.redemptions |
This bot's configured enabled redemption IDs, names, costs and action kinds. |
ctx.test |
True for simulation. |
api.version |
1. |
api.rng(min,max) |
Inclusive whole-number random value. |
api.random() |
A random number from 0 up to, but excluding, 1. |
Supported events are chat, follow, gift, likes, membership, song_started, song_finished, timer, and manual. Availability follows provider support. Gift values use the platform's existing normalization. Chat commands match the first word; optional keywords use case-insensitive containment. Without filters, a chat subscriber receives all admitted chat events. Bot-generated and configured ignored-user messages are excluded. Avoid subscriptions to every chat message when a command filter is enough.
Timers run while the bot runs, including when no stream is connected. Use your settings/state to gate a game. For a timer to send chat, explicitly choose a platform and one of this bot's configured channels in the chat effect. Queued runs expire after 60 seconds. Event admission is capped at 120 jobs per minute across your bot's add-ons, with at most 100 waiting jobs. Excess work is dropped to protect normal bot activity.
Return any of these fields:
state: replacement private JSON state, at most 64 KiB. Requires state permission. Omit to keep the previous state.overlay: replacement display data, at most 32 KiB. Requires overlay permission. Only put information intended for the overlay here.values: named string/number/boolean values, at most 8 KiB total. Names begin with a letter and contain letters, digits or underscores.effects: a list of proposed actions. ForgeCaster checks that each action is permitted and targets your bot before applying it.
Allowed effects
| Permission | Example | Scope |
|---|---|---|
| chat | {type:'chat', text:'Hello!'} |
Replies to the event's configured channel. For timers, add platform:'tiktok', channel:'yourchannel'. External/unconfigured chat targets are rejected. Uses the normal chat sending and pacing settings. |
| points | {type:'points', delta:10} |
Adds/subtracts the triggering viewer's points. To target another known viewer in this same bot, add viewer:ctx.viewers[0].key. Insufficient points fail the run. |
| queue | {type:'queue', action:'promote', tier:'tier_100'} |
Promotes the triggering viewer's eligible queued request using existing queue rules. action:'move_one' is also supported. |
| queue | {type:'redeem', action_id:'YOUR_CONFIGURED_REDEMPTION_ID'} |
Runs an enabled points redemption through the ordinary cost, balance and action checks, including configured skip-current redemptions. This must be the only effect in the run. |
| goals | {type:'goals', id:'YOUR_CUSTOM_GOAL_ID', action:'add', value:1} |
Updates a Custom goal in this bot. set and reset are also supported. Provider-driven goals cannot be rewritten by scripts. |
The default is six effects per run. Total absolute point changes are limited to 10,000 per run and 600,000 per hour across your bot's add-ons. Point debits count toward the limit too. Add-ons can use only the documented effects; direct queue deletion, arbitrary provider API calls, account or billing changes, secret access, shell commands and filesystem access are unavailable.
Ordinary effect batches commit atomically: if a later effect fails, earlier database changes roll back. Redemptions use the existing durable redemption system and a saved proposal/receipt so retries do not choose a different random purchase or charge twice. External providers still have their own delivery limits and failure modes. Chat queued while sending is disabled does not send.
In Actions & Events, select Run a published custom add-on and copy its ID from the add-on card. It receives a manual event. The add-on must be published, enabled and authorized for the requested actions.
Custom template values
After a run returns values:{roll:13}, use {addon:chat-roll:roll} in supported chat templates. The slug and value name are explicit to prevent collisions between packages. Missing/unavailable values become empty text.
The optional Pure template helper returns only {values:{...}}. It receives the same context and runs with the event handler in the isolated runner. It cannot return effects or save state. Main-handler values override matching helper values.
Values refresh when an add-on event completes. Rendering an ordinary chat message reads the latest committed values and never executes untrusted code or waits for a script. For a personalized immediate response such as !roll, return a chat effect from the event handler instead of using a cached shared value.
Settings boxes
Settings definitions are declarative JSON; they cannot add executable code to the control panel. Save the schema to regenerate its fields.
[
{"key":"maximum","label":"Maximum roll","type":"number","min":1,"max":100000,"default":20},
{"key":"color","label":"Accent color","type":"color","default":"#a370ff"},
{"key":"title","label":"Title","type":"text","default":"Community roll"},
{"key":"celebrate","label":"Celebrate wins","type":"toggle","default":true},
{"key":"style","label":"Style","type":"select","options":["compact","large"],"default":"compact"}
]
Up to 30 settings are allowed. Supported types are number, text, color, select, toggle and asset. An asset setting selects a name from your embedded assets object. Supply a valid default for every setting so imported packages can start with fresh defaults. Unknown settings and unsupported HTML controls are rejected.
Coded overlays
HTML goes in HTML, styling in CSS, and script in Browser JavaScript. The iframe receives only your overlay data, validated settings and embedded assets:
addEventListener('message', event => {
if (event.data?.type !== 'forgecaster') return;
const {data, settings, assets} = event.data;
const label = document.getElementById('result');
label.textContent = data?.text || 'Waiting…';
label.style.color = settings.color;
});
For a progress bar, return overlay:{current:37,target:100} and set its fill width to a clamped percentage when new data arrives. The trusted display wrapper refreshes data about once per second. Animate smoothly with CSS transitions or a modest requestAnimationFrame loop.
Your overlay runs in an isolated display. It receives only the display data, settings and assets shown above, with no access to your control panel, login cookies or another account's data. Overlay code cannot send commands or award points; use permitted effects in your event handler for those actions. Anyone you give a source link to can view that display, so keep the link private.
Use addEventListener instead of HTML onclick attributes: inline event attributes are blocked. Remote scripts, fetch/WebSockets, CDN assets, frames, forms, popups and workers are blocked. Bundle small code in the package. Up to ten PNG/JPEG/WebP data-URL assets are supported, each at most 128 KiB and 2048 pixels per dimension. SVG and arbitrary file uploads are not supported. Use textContent for viewer names instead of innerHTML.
Browser animation runs on the machine displaying it. A badly written browser loop can slow your streaming application. Keep animations light, and remove a malfunctioning source from LIVE Studio/OBS before debugging.
Import, export and sharing
Export produces one .fcaddon.json package. It contains source, schema, settings and embedded assets, but no viewer balances, private state, credentials, source tokens or execution history. Import creates an independent disabled draft with a new ID and slug, resets settings to declared defaults and requires a new test and publication. Rebind custom goal/redemption IDs for the receiving bot.
Private is the default sharing choice and does not opt your package into transfer or community reuse. Transfer gives permission for a copy to be imported into another eligible account with your author credit preserved. Community additionally allows consideration for an official ForgeCaster feature. These choices do not automatically publish your package or remove its attribution.
Execution history keeps up to 1,000 records / seven days. Packages keep their current draft and up to 20 published versions. Export important creations for long-term safekeeping. Do not include passwords, API keys or private viewer information in package source or overlay data.
Execution and package limits
Event handlers run in an isolated JavaScript environment with access only to the documented ctx data and api helpers. Use ctx.state and return state to retain data between runs; ordinary JavaScript variables do not persist. Network requests, filesystem access and external imports are unavailable.
Each handler or optional helper has a two-second execution deadline, 32 MiB of memory and a bounded instruction budget. Input is limited to 512 KiB and output to 128 KiB. Keep loops bounded, return promptly and store only the data your add-on needs. If execution exceeds a limit, inspect Execution history, simplify the code and test the saved draft again.
Packages are at most 512 KiB each. Event JavaScript, HTML and browser JavaScript are each at most 64 KiB; CSS is 32 KiB and the optional value helper is 8 KiB. The default total local package/version budget is 16 MiB, with at most 50 local packages including archives. There are no npm/Python imports or arbitrary uploaded executables.
Review code before importing or publishing it. Use Test simulated event and Preview overlay, then verify your add-on on a private stream before using it with a live audience.
Local avatar interactions
Master Maker add-ons can declare the avatar permission and emit a bounded named signal:
return {effects: [{type: "avatar", signal: "bonk"}]};In Desktop VTuber Studio, connect your tenant, create a saved prop or expression, then add an interaction with trigger addon and match bonk. The local rule chooses the action, cooldown and physics. Signals expire after five seconds; disconnected clients do not replay old effects.
This permission cannot run desktop code, access local files, upload camera frames or change broadcaster controls. Raw scripts continue to run in the isolated Master Maker runner. VTuber Studio is a development candidate; see the Studio guide for setup and current compatibility limits.