Skip to content

Author a custom graphic in Studio

Write HTML, CSS and JavaScript beside a live preview, connect channel data, and share your design in a pack.

8 min readUpdated

Before you start

Use a Custom graphic layer when you want your own layout, animation or canvas drawing inside an overlay. You need an overlay open in Studio and some HTML, CSS or JavaScript knowledge, or a connected AI assistant to help write the source. Your graphic can fill the overlay or sit beside built-in layers.

Upload any pictures, sounds or videos to your media library first. Declare any channel variables you want to display on Variables. This guide uses a raid card with a colour setting; it needs no media or variables.

1. Open code beside the preview

  1. Open Overlays, then Open in Studio on your overlay.
  2. Choose Add a layer, find Custom graphic under Media, and add it.
  3. Select its layer and press Edit graphic code in the Graphic section.
  4. Use the HTML, CSS and JavaScript tabs to change the card. The preview sits beside the code on wide screens and below it on narrow screens.

The starter already has a card, an Accent colour setting and a raid animation. For a first edit, change the text inside the HTML card or its padding in CSS. Auto-run refreshes the preview after a short pause in typing. Turn it off and choose Run code when you prefer to run changes yourself.

Changes save to your Studio draft. Back to Studio closes the workspace; Escape does the same. The draft does not reach OBS until you publish.

Studio’s expanded code workspace with JavaScript on the left and a raid card, playback and event simulation on the right.
JavaScript beside the graphic preview, with playback, a sample raid and Output. Click to enlarge.

2. Connect data and expose settings

Open Data & settings in the workspace.

  1. Under Libraries, enable GSAP for animation or PixiJS for canvas/WebGL drawing. These are the versions included with Bloopbot.
  2. Under Events, tick only the events your code reads. The starter selects raid and uses bloop.onEvent("raid", handler).
  3. Under Variables, select declared channel variables. Read their current values with bloop.getVariables() or receive updates with bloop.onVariables(handler).
  4. Under Media, give a library file a name such as portrait. Read its local URL as bloop.assets.portrait.
  5. Under Exposed settings, add a text, colour, number, flag or select control. Read it as bloop.settings.name. These controls appear in the normal Studio panel, so someone adding your pack can customise it without editing code.

For example, a number variable named wins can fill a score:

bloop.onVariables(values => {
  document.querySelector("#score").textContent = String(values.wins ?? 0);
});

Add an element with id="score" to HTML and select wins under Variables first. Channel variable names use lowercase letters, digits and underscores. A flow can change that variable when a command or event happens; the graphic displays it.

The custom graphic’s Data and settings tab shows bundled GSAP and PixiJS, permitted events and variable bindings beside the preview.
Choose the bundled libraries, event subscriptions and channel variables in Data & settings. Click to enlarge.

The SDK reference covers every method, the manifest and limits. Source runs in its own sandbox and receives the data you selected. It cannot read the dashboard, cookies or storage. External script imports, fetch, sockets and nested players are blocked; bind library media instead. Named custom messages, leaderboard boards and Stage queues use the separate HTML overlay SDK.

3. Test a chosen moment

  1. Under Simulate an event, choose raid.
  2. Leave the sample fields as {"name":"Sample raider","viewers":42} and choose Send event.
  3. Press Play preview to watch the animation. Pause preview stops the shared clock.
  4. Move Preview time to revisit a moment. The graphic reruns its code and replays the recorded events up to that time.
  5. Choose Reset preview to clear sample events and start again. Preview length in Data & settings sets the time range, up to 60 seconds.

The name should change to Sample raider and the card should animate. These events stay in the preview; they do not trigger Twitch, a flow or an OBS test. Output shows script and loading errors.

Use bloop.timeline() for GSAP animations, bloop.schedule() for delays and bloop.onTick() for canvas updates. CSS animations also follow the preview clock. Native timers and a library's independent ticker keep their own clock and cannot reproduce a paused or sought preview. A Pixi application should stop its ticker and render from onTick.

4. Publish and share

  1. Choose Back to Studio, place and size the layer on the canvas, and check the whole overlay.
  2. Press Publish when you want your existing OBS Browser Source to use the new graphic.
  3. On the overlay's card, choose Add to pack… and select your pack or create one.
  4. Share it using Marketplace or Bundle file (.bloop.zip). A flow-only share link does not carry overlays.

The pack carries the graphic's source, controls, data declarations and bound media. Include the flows that drive its variables. A recipient gets their own media references and missing channel variable declarations; a compatible variable they already have keeps its value. Pack updates use the existing local-change review, so editing source or a control counts as a local change.

Only share source and media you have permission to distribute. Installing a graphic runs its JavaScript with the channel data its manifest selects. Review its source and declarations in Studio before publishing it to OBS.

Ask an assistant to author it

Allow your connected assistant to read and edit overlays. Ask it to discover graphics, edit the complete Studio draft and render a preview before publishing. You can give it a concrete brief:

Create a custom graphic in Studio: a transparent raid card with an editable accent colour. Use the graphics layer and bundled GSAP. Subscribe only to raid. Render a preview at 500 ms with a sample raid from PixelPal, then leave the source in the draft for me to review.

An assistant can supply sample event fields, variable values and a timestamp for a rendered preview. Those are simulated values. If you change Studio while it works, its old draft revision is refused; ask it to reread the draft.

If it does not look right

  • Blank preview: read Output, check your element IDs, and choose Run code after fixing the source. An undeclared event or a timeline without GSAP reports an error.
  • A variable is missing: declare it on Variables, select it in Data & settings and use its lowercase key. Viewer variables are unavailable to graphics.
  • Media is missing: choose an existing library file for its binding. Graphics load at most 8 MB per file and 32 MB total; larger files need a smaller version even if the library accepted them.
  • Seeking differs from playback: use the SDK clock methods and stop independent tickers. Preview history keeps the latest 256 events; reset before a fresh test.
  • A save is refused: the workspace lists the setting field and reason. Repair the label, default, options or value before publishing.
  • OBS has the older graphic: close the workspace and Publish the Studio draft. Keep the existing overlay Browser Source URL.
A little guidance. A lot of possibilities.Something not working?