# Make a custom Twitch overlay with HTML and JavaScript

Write your own Twitch overlay in HTML, CSS and JavaScript beside a live preview, make it react to raids, follows and subs, and put it in OBS without hosting anything.

Updated 7 October 2026

## The short answer

In Bloopbot you write a custom Twitch overlay in HTML, CSS and JavaScript (or TypeScript) beside a live preview, connect it to raids, follows, subs, cheers and your own channel variables, and show it in OBS through one Browser Source. Bloopbot hosts it and sends it the events, so there is no server to run, no build step and no Twitch API key to manage. This guide builds a raid card that shows the raider's name and party size.

You need:

- Your Twitch channel connected to Bloopbot ([Get started](https://bloopbot.com/docs/getting-started)).
- An overlay to put it in. Make one on **Overlays** if you have none ([Add an overlay to OBS](https://bloopbot.com/docs/widgets-in-obs#choose)).
- OBS on the computer you stream from.
- Some HTML and CSS, or a [connected AI assistant](https://bloopbot.com/docs/connect-an-ai-assistant) to write it with you.

## 1. Open the code beside the preview

1. Open **Overlays**, then **Open in Studio** on your overlay.
2. Choose **Add a layer**, then press **Create custom graphic** at the foot of **Add**.
3. Select the new layer and press **Edit graphic code** in the **Graphic** section.

The workspace has **HTML**, **CSS** and **TypeScript** tabs on one side and the preview on the other. Plain JavaScript is valid TypeScript, so you can write either. **Auto-run** refreshes the preview a moment after you stop typing. The starter is already a raid card; you can edit it or replace it.

![Studio’s expanded code workspace with TypeScript on the left, the Script language choice in the toolbar, and a raid card, playback and event simulation on the right.](https://bloopbot.com/docs/screenshots/studio-graphics-code.jpg)

_The code workspace: the script on the left, the graphic's preview, playback and sample event on the right._

## 2. Write the card

In **HTML**:

```
<div id="card">
  <strong id="name">Someone</strong> is raiding with <span id="viewers">0</span> viewers!
</div>
```

In **CSS**, style it as you like, for example:

```
#card { font: 700 40px system-ui; color: white; background: #6441a5; padding: 24px 32px; border-radius: 16px; opacity: 0; }
```

In **TypeScript**, show the card when a raid arrives and hide it again after a few seconds:

```
bloop.onEvent("raid", (event) => {
  document.querySelector("#name").textContent = event.name;
  document.querySelector("#viewers").textContent = String(event.viewers);
  bloop.timeline()
    .to("#card", { opacity: 1, duration: 0.4 })
    .to("#card", { opacity: 0, duration: 0.4 }, 5);
});
```

`bloop.timeline()` is a GSAP timeline that follows the preview's clock. The starter already ticks **GSAP** under **Data & settings → Libraries**; keep it ticked. CSS animations work without it.

## 3. Choose what it listens to

Your code hears only the events you tick.

1. Open **Data & settings**.
2. Under **Events**, tick **raid**. The starter has it ticked already. **follow**, **sub**, **resub**, **gift** and **cheer** work the same way.
3. Choose **Back to Studio**. In the layer's **Content** tab, **Triggered by flows** lists a flow for each event. If **raid** says **Needs a flow**, choose **Set up flow**.

A flow is what delivers a Twitch event to your overlay, so you can add a check in it later, such as showing the card only for raids over 10 viewers. To show a number that changes, such as a death counter, tick it under **Variables** and read it with `bloop.onVariables()`; [connect data and expose settings](https://bloopbot.com/docs/author-custom-graphics#data) shows how.

## 4. Test it without going live

1. In the workspace, under **Simulate an event**, choose **raid**. The sample is `{"name":"Sample raider","viewers":42}`; change the name or the number if you like.
2. Press **Play preview**. The card should show _Sample raider is raiding with 42 viewers!_ and fade away after five seconds.
3. Check **Output** if nothing happens: it shows script errors and anything that failed to load.

Simulated events stay in the preview. They don't reach Twitch, your flows or OBS.

## 5. Put it in OBS

1. Choose **Back to Studio**, place and size the layer on the canvas, and press **Publish**. Review the queued flow for **raid** and choose **Create and switch on**.
2. If this overlay isn't in OBS yet, copy its address from **Overlays** and add it to OBS as a **Browser Source** at 1920 × 1080, as [Add the Browser Source](https://bloopbot.com/docs/widgets-in-obs#obs) shows. An overlay already in OBS picks up the new layer by itself.
3. To see it in OBS before a real raid, open **Simulate** on the Studio canvas and, under **Test events**, tick **Also play on the live overlay in OBS — viewers will see it**, then play a raid. If you are live, your viewers see the test too.

The card now plays on stream every time someone raids you.

## Prefer your own HTML file?

To keep the file on your own computer and point OBS at it, use a custom overlay instead: Bloopbot gives you a starter file and a private address that sends it the events you choose. [Connect your own HTML overlay](https://bloopbot.com/docs/custom-widgets) walks through it. A custom graphic in Studio is easier to share, because it can go in a pack or on the Marketplace.

## Troubleshooting

- **The preview stays blank.** Open **Output**. A script error or a library you use but haven't ticked under **Libraries** shows there.
- **A font, picture or script from another website doesn't load.** Graphics run in a sandbox that blocks remote scripts and media. Google Fonts load, pictures from other websites load through `bloop.loadImage()`, and your own files go in your [media library](https://bloopbot.com/docs/choose-and-upload-media). [Author a custom graphic in Studio](https://bloopbot.com/docs/author-custom-graphics#data) lists what is allowed.
- **It works in the preview but not on stream.** Check you pressed **Publish** and switched on the raid flow, and that the scene with the Browser Source is showing. [If you cannot see anything](https://bloopbot.com/docs/widgets-in-obs#check) has more checks.
- **Every method and limit:** the [Custom graphics API](https://bloopbot.com/developers/graphics).
