Inspiration
We wanted chat's ideas to become something the streamer has to face, then give that same audience a reason to help. ChatMade turns a few minutes between stream segments into a shared creature-making game. Viewers contribute through the Twitch chat they already use.
What it does
ChatMade is a standalone audience-participation game: chat collectively chooses a creature's ingredients, then helps the streamer survive its attacks.
- Viewers send
!body,!powerand!weaknessideas in Twitch chat. The host reviews suggestions before they appear on broadcast. - Approved ideas become three recipes. Chat votes with
!vote 1,!vote 2or!vote 3; the host checks the supported mechanics and explicitly approves the winner. - The creature is revealed with selected contributors credited. The streamer uses WASD or arrow keys to dodge for up to 60 seconds with three hearts.
- Viewers send
!helpto activate its weakness. The default requires three different viewers within 15 seconds; a one-viewer setting supports small-channel testing. - The round ends SURVIVED or CAUGHT, saves a local result, and offers a shareable PNG with optional contributor names.
Powers map to three bounded attack patterns: charge, bounce and projectile burst. Weaknesses stun, slow or shrink danger zones. The host sees the actual mechanic before approval. The current build uses the same original jelly-knight artwork for every recipe; body suggestions receive credit but do not generate new art.
How we built it
The application runs locally alongside OBS. React 19.3.1 renders the host desk and broadcast layout; Canvas 2D draws the arena; Node.js runs the authoritative game and Twitch adapter. TypeScript 5.9.3, Vite 7.3.7 and ws 8.22.0 are pinned through the dependency lockfile.
Twitch Public-client device authorisation requests only user:read:chat. Twitch API token validation identifies the authorised streamer and EventSub WebSockets deliver channel.chat.message events. Tokens remain in backend memory; each streamer connects their own channel without source edits or a separate bot account. A separate read-only browser page is designed for an OBS Browser Source. Saved round records retain selected credits and outcomes, not OAuth tokens or a raw-chat archive.
How we used Codex
I directed the product and approved decisions in one main Codex chat. Codex challenged the audience roles and scope, helped choose cooperative survival and bounded mechanics, recorded architecture decisions, then built the TypeScript game, React interface, Twitch adapter and macOS preview packaging.
Codex also wrote regression/integration tests and debugged concrete problems: private-file exposure through development-server paths, attack warnings disappearing during rescue effects, fixed projectile angles, and inherited Node flags breaking packaged startup. At my request, it drove the first real Twitch smoke test: ideas reached moderation, a vote counted, !help activated rescue, and a result PNG downloaded successfully.
How we used AI
Codex was the development assistant. Gameplay, recipe mapping and physics execute deterministic application code. This version does not call a runtime language or image model and does not generate creature artwork.
Challenges we ran into
Creative chat suggestions need predictable rules. We kept free-text ideas but showed their bounded gameplay mapping before host approval. Votes recommend a recipe; they cannot bypass that approval.
Local broadcast tooling also needs a clear control boundary. Host mutations require a private key and accepted origin; the broadcast view cannot control the game. Twitch credentials stay in the backend.
The first live test exposed repeated idle keepalive timeouts followed by recovery. That reliability finding is still open; mock reconnect tests are not evidence that live reconnect is fully reliable.
Accomplishments we're proud of
- A complete create, vote, reveal, survive and export loop.
- 28 passing automated tests on 2 November, including mocked Twitch authentication, reconnect and duplicate-delivery cases.
- One completed real Twitch round on
jwlaicloud: five accepted commands, zero rejected commands, one rescue, CAUGHT at 13.3 seconds, and a verified 1200 × 675 result PNG. This used the broadcaster's account and rescue threshold 1, not three viewers. - A publisher-configured macOS Apple Silicon preview with a bundled Node runtime passed startup, host/broadcast, private-launcher and shutdown checks on the development Mac.
What we learned
A viewer's idea needs a visible consequence they can understand. Showing attack and rescue mechanics before approval made the relationship between creative text and playable rules explicit. We also learned to separate mocked integration coverage from real Twitch evidence: the first live round validated delivery while exposing a reliability issue the mock suite had not established in production.
What's next
Investigate idle keepalive timeouts, run a three-viewer playtest, check OBS readability/performance, and validate setup with another streamer on a clean Mac. Runtime generation remains a future decision with provider and spending limits still unresolved.
Testing instructions
Run locally from source using the repository instructions. Sample mode needs no Twitch login and uses explicitly simulated participants. For live testing, connect your own Twitch channel and send commands through ordinary Twitch chat. No runtime AI API key or separate bot account is required.
Judge quick start: https://github.com/jwlai-cloud/ChatMade/blob/main/docs/JUDGE_TESTING.md
Architecture: https://github.com/jwlai-cloud/ChatMade/blob/main/docs/ARCHITECTURE.md
Built With
- html5
- node.js
- openai-codex
- react
- twitch
- twitch-eventsub
- typescript
- vite
- websocket
Log in or sign up for Devpost to join the conversation.