Twitch + emotes
Setting up the Twitch dev app and the emote pipeline.
The Twitch app credentials power two things:
- Setup wizard — the channel lookup that seeds your profile
- Emote pipeline — 12-hourly cron that pulls from 4 providers and merges into KV
Both use the client_credentials grant — no user OAuth flow, no redirect URL, no callback.
Twitch dev app
Create the app
dev.twitch.tv/console/apps/create
- Name:
HowlCast - OAuth Redirect URL:
https://tv.your-domain.tv/auth/twitch/callback(placeholder — never hit) - Category: Application Integration
- Client Type: Confidential
- Organization: None
Copy the credentials
Click Manage on the app. Copy the Client ID. Click "New Secret" → copy the Client Secret (you only get to see it once).
Set the secrets
echo "TWITCH_CLIENT_ID=xxx" >> apps/server/.env
echo "TWITCH_CLIENT_SECRET=yyy" >> apps/server/.env
bun run deploy # pushes to prod via alchemyEmote pipeline
The cron in apps/server/src/index.ts fires every 12 hours (0 */12 * * *). It:
- Reads
channelConfig.broadcasterTwitchIdfrom D1 - Fetches a Twitch app token (cached 50min in
EMOTES_KVattwitch:apptoken) - Fans out to four provider fetchers in parallel:
- Twitch Helix (subscriber + global emotes)
- 7TV (
/v3/users/twitch/{id}) - BTTV (
/cached/users/twitch/{id}) - FFZ (
/v1/room/id/{id})
- Merges results into one map, writes to
emotes:currentin KV - Provider failures fail-soft — the map is rebuilt from whichever providers responded
Provider setup
For emotes to actually appear, you need accounts at the providers and emotes assigned to your Twitch channel:
7TV
7tv.app → sign in with Twitch → Profile → Emotes → upload PNGs. Usable by anyone in your chat. Free.
BTTV
betterttv.com → sign in with Twitch → upload emotes to your channel.
FFZ
frankerfacez.com → sign in with Twitch → submit a New Emote → upload PNG → wait for moderator approval (1–7 days).
Twitch (subs + global)
Subscriber emotes only appear if you're an Affiliate / Partner. Global emotes (Kappa, etc.) auto-included.
Manual refresh
Don't want to wait for the cron? Hit Channel → Emotes → Refresh in the dashboard. Same handler, runs immediately. Bumps the emotes:current KV value and the channel page picks up the new map on next chat connect.
Troubleshooting
- No emotes show after upload — check
bun run deploypushed Twitch creds. Then click Refresh in the dashboard. Then check the worker logs forgetTwitchAppTokenor fetch failures. - "Twitch app token failed" — Client Secret rotated? Generate a new one in the Twitch dev console.
- Some providers missing, others working — provider outage. Fail-soft means the next cron retries.
Next: Branding.