Inspiration
A raid is the biggest moment of arrival a Twitch community has: a whole audience lands in chat at once. Most of the time that moment is a handful of "welcome raiders" messages that scroll away in seconds. I wanted the welcome to be something the whole chat does together, and something the stream remembers.
What it does
When a raid arrives, chat gets 30 seconds to type !welcome.
- Each chatter counts once. Spamming doesn't help. What counts is how many people show up.
- The goal scales with the raid, so small streams and big streams can both win:
$$\text{goal} = \min\left(8,\ \max\left(1,\ \left\lceil \frac{\text{raiders}}{4} \right\rceil\right)\right)$$
- As welcomes come in, the Welcome Wisp builds up on the stream overlay.
- Hit the goal and the Wisp stays on stream as a keepsake of that raid. If time runs out, chat still keeps a partial Wisp, so small communities never walk away with nothing.
How I built it
I built the whole project in a single OpenAI Codex thread.
- Server: Node.js, with routes, JSON endpoints and live updates to the overlay.
- Twitch: OAuth with the
user:read:chatscope, token refresh, and EventSub over WebSocket forchannel.raidandchannel.chat.message. The app only reads chat and never posts. - Game rules: the 30-second round, raid-size goal scaling, one welcome per chatter, and exact
!welcomematching. - Overlay: an OBS browser source with live progress, a countdown and the Welcome Wisp.
- Control page: the streamer's view, with a goal preview, a raid simulator and demo chat, so anyone can try it without a live stream.
Codex also handled the edge cases: a second raid arriving mid-round, clearing the old keepsake, reconnecting EventSub when Twitch moves the WebSocket session, and rejecting malformed requests.
What I learned
- Count people, not messages. Counting distinct chatters changes the feel completely: it becomes a group effort instead of a typing race.
- Fairness has to scale. A fixed goal punishes small streams, so the goal grows with the raid but is capped, so a big raid doesn't become impossible.
- Twitch's EventSub over WebSocket is a clean way to build a local tool. There's no public server, and it just runs alongside OBS.
Challenges
- You can't trigger a raid on demand. To build and test it, I added a raid simulator to the control page. Chat comes through Twitch live, and raids can be simulated for testing and demos.
- Overlapping raids. A second raid can land while a round is still running, so the rules had to decide cleanly what happens to the round already in progress.
- Keeping it safe. The control page has no login, so it's designed to run locally next to OBS, never exposed publicly.
What's next
A shelf of Wisps: one for every raid a community has welcomed, so a channel can look back at its own history of growing.
Built With
- codex
- css
- html
- javascript
- node.js
- obs-studio
- openai
- server-sent-events
- twitch
- twitch-eventsub
- twitch-oauth
- websocket
Log in or sign up for Devpost to join the conversation.