Inspiration

Twitch chat moves quickly, and individual viewers can feel like their messages disappear in the stream. We wanted to give each channel a recognizable mascot that reacts to chat in the moment and adds personality to the broadcast.

What it does

MurMur lets streamers customize an animated mascot’s name, shape, color, expression, and motion. When chat reactions are enabled, TypeSafe Jev classifies individual Twitch chat messages and updates the mascot’s expression.

Streamers can also enable short AI-generated chat replies, show the mascot through a Twitch Video - Fullscreen Extension or an OBS browser source, and start Twitch polls manually from the dashboard. Poll creation depends on Twitch account eligibility.

How we built it

We built the dashboard and backend with Next.js, React, TypeScript, and Node.js. A separate worker receives Twitch chat through EventSub WebSockets. TypeSafe Jev classifies each eligible message and decides whether a reply would fit. If it recommends one, Groq generates a short reply; MurMur validates it and applies cooldowns before sending it through Twitch Extension Chat.

The Extension viewer receives expression updates through Twitch Extension PubSub. Broadcaster OAuth, chat permissions, poll creation, and Extension authentication use Twitch APIs. Mascot sessions are stored in a JSON file, and Twitch tokens are encrypted before storage.

Challenges we ran into

Twitch Extension setup has several moving pieces: viewer and config pages, local testing URLs, backend origins, JWT verification, and the Extension’s Chat capability. Keeping mascot state in sync across the dashboard, Extension viewer, and OBS overlay was another challenge.

We also had to account for Twitch’s poll eligibility rules. Poll creation is restricted to Affiliate and Partner channels, so MurMur reports that limitation instead of treating it like a general API failure.

Accomplishments that we're proud of

We built a path from a Twitch chat message to a Jev-classified mascot expression and an Extension PubSub update. We also connected optional Groq replies to Twitch chat, created a streamer dashboard for manual poll creation, and kept an OBS browser-source overlay available as another way to display the mascot.

What we learned

We learned how Twitch OAuth scopes, EventSub WebSockets, Extension JWTs, Extension Chat, and PubSub fit together. We also learned to keep model decisions separate from application actions: Jev classifies messages, while MurMur’s code applies thresholds and cooldowns before sending a reply. Chat text is sent to AI providers when needed, so privacy needs to be part of the product design.

What's next for MurMur

We’d like to add aggregate community mood, configurable mascot personality and vocabulary, and an approval inbox for proposed replies. We also want to replace the single-file session store with shared database storage, improve moderator controls, add automated tests, and make deployment and Extension setup easier.

Built With

Share this project:

Updates

Submission history