Inspiration
We were building a multi-character 3D AI companion platform — think Character.AI but with Unity WebGL avatars and real personalities. Midway through, we realized our characters were doing something interesting: reacting to events in real time and speaking with distinct voices. That's exactly what streamers want. The pivot wasn't planned. We just noticed our companions belonged on stream.
What it does
Machi Kick Extension connects your Kick channel to an AI character overlay for OBS. When viewers follow, subscribe, or gift, the character generates a one-of-a-kind verbal reaction — in character, in their own voice — and speaks it live over your scene. No canned alerts. Every reaction is unique. To go into the Kick extension of the app, you must visit the /kick-extension route.
How we built it
We used Kick's OAuth 2.0 + PKCE flow to connect streamer accounts, then registered webhooks dynamically at connect time via Kick's event subscription API. Webhook payloads are verified with RSA-PSS signatures against Kick's public key. Events are forwarded to the OBS browser-source overlay over SSE. The LLM generates a character-appropriate one-liner in response to each event, and TTS speaks it immediately. The overlay URL is unique per streamer: just paste it into OBS as a Browser Source.
Challenges we ran into
Kick's 2FA flow doesn't play nicely with OAuth popups, hence the cookie state doesn't carry over cleanly, causing verify-2FA to return 400. We also hit invalid_client during token exchange until we pinned down an exact redirect URI match. Webhook signature verification required careful handling of the RSA-PSS saltLength parameter to avoid silent rejections.
Accomplishments that we're proud of
The entire event pipeline from Kick firing a webhook to the character speaking a reaction works end to end with zero pre-written responses. Every reaction is generated live. We also extracted the Kick crypto and event logic into a standalone module with full unit test coverage: PKCE math, all five event types, signature verification with real RSA key pairs, and public key caching.
What we learned
OAuth in popups is fragile. Redirect-based flows are more reliable when 2FA or strict CSRF protection is involved. We also learned that Kick's invalid_client error can mean either wrong credentials or a redirect URI mismatch — the error message doesn't distinguish between the two.
What's next for Machi Kick Extension
Bring the full 3D Unity WebGL characters into the overlay so reactions aren't just audio, the avatar animates and lip-syncs live on stream. Add a hype meter that builds across events and triggers special animations at thresholds. Support chat commands so viewers can interact with the character directly.
Built With
- claude
- kick
- node.js
- obsstudio
- react
- tts
- typescript
- vitest
- voicevox
Log in or sign up for Devpost to join the conversation.