Skip to content

Repository files navigation

HowlBox - Themed Twitch Chat Overlay for OBS

HowlBox is a self-hosted, client-only Twitch chat overlay for OBS browser sources. It joins Twitch chat anonymously, renders native Twitch, 7TV, BTTV, and FrankerFaceZ emotes with badge art, and takes its entire configuration from URL query parameters, so an OBS source URL is the whole setup.

Reading chat anonymously is what removes the account, and it is also the limit: HowlBox cannot send messages, moderate, or show follower alerts (follows only arrive over EventSub). Subs, gifts, raids, and cheers do arrive over anonymous IRC, and the events parameter renders them. If you need to send, moderate, or see follows, you need an overlay with a backend.

Your chat. Your colors. Your howl.

Features

  • Anonymous chat connection - Read-only Twitch chat over @twurple/chat. No account, no keys, nothing to expire mid-stream.
  • 31 themes in four families - Clean (wolf glass, Liquid Glass, midnight, daylight, high contrast, bare text, gold luxe, brutalist, holographic), Gamer (synthwave neon, Xbox, galaxy, ember, cyberpunk, sci-fi HUD, aurora), Cozy (kawaii pastel, mocha, sakura, forest, deep sea, frost, sticky note, comic), and Retro (CRT terminal, Windows 95, Windows XP, pixel arcade, Game Boy, VHS, vaporwave). Nine of them carry color variants through variant, for 45 looks in total. All CSS-variable driven, and a browser source downloads only the CSS for the theme in its URL.
  • Three display modes - Transparent messages over gameplay (bg=off), one themed backdrop panel (bg=panel), or per-message bubbles (bg=bubble).
  • Full emote support - Native Twitch emotes plus 7TV (including zero-width overlay emotes), BTTV, and FrankerFaceZ, resolved per channel and cached in localStorage.
  • Adjustable emote size - emotescale (1 to 4, half steps) grows messages that are nothing but emotes, without inflating regular text messages.
  • Ticker mode - scroll=ticker lays chat out as one horizontal lane sliding right to left, for a strip under the gameplay instead of a column beside it. scrollspeed runs it from 1x to 5x, with 1x a deliberate crawl. A lane fits about one message every eight seconds at 1x, so on a fast channel it shows a sample of recent chat rather than all of it.
  • Badge art without secrets - Every global and per-channel Twitch badge (including subscriber and bits art) via public, CORS-safe APIs, plus custom badge art overrides inline through the badgeart parameter or hosted in a public GitHub gist through badgegist.
  • Pronoun badges - Opt-in (pronouns=true) pronoun badges next to names, from pronouns.alejo.io, the service 7TV and FrankerFaceZ read. Each chatter's login is looked up there; enable it only if that third-party call is acceptable for your channel.
  • Profile picture avatars - Opt-in (avatars=all or avatars=subs) chatter avatars before names, fetched in batches from api.ivr.fi and cached locally. subs mode only looks up subscribers and founders.
  • Sub, cheer, raid, and first-chat alerts - Opt-in (events=sub,cheer,raid,first,announce or events=all) event rows for subs, gift bombs, raids, cheers, first-time and returning chatters, and announcements, riding the same anonymous connection as chat. A 100-gift bomb collapses to one row instead of one hundred.
  • Moderation aware - Deleted messages, timeouts, and bans vanish from the overlay instantly. An optional delay holds non-mod messages so moderation lands before anything renders.
  • Filters - Hide known bots, hide !commands, hide specific users, or run featured mode showing only chosen users.
  • URL-only configuration - Every option is a query parameter. No config files, no dashboard, no stored state.
  • Configurator page - Pick options live at /config with a real overlay preview, then copy a ready OBS source URL. The landing page at / shows a theme-switching demo.
  • OBS-optimized - Transparent from first paint, zero blur filters (safe on CPU-rendered setups), event-driven reconnects that survive hidden-source timer throttling, and a visible connection status pill.
  • Stable styling hooks - Every element carries hb-* class names as a contract for the OBS Custom CSS field.

Getting Started

  1. Clone the repository:

    git clone https://github.com/mrdemonwolf/howlbox.git
    cd howlbox
  2. Install dependencies:

    bun install
  3. Start the dev server:

    bun run dev:web
  4. Open http://localhost:3001 for the landing page, then head to http://localhost:3001/config to build a URL and add it as an OBS browser source.

Usage

Build an overlay URL with the builder at /config, or hand-write one:

/overlay?channel=mrdemonwolf&theme=wolf&bg=bubble&hidebots=true&fade=30

The full reference lives at /docs on the deployed site (mrdemonwolf.github.io/howlbox/docs): every parameter with its own anchor, both custom badge art formats, the hb-* Custom CSS contract, and troubleshooting. The table below is the short version.

Parameter Values Description
channel Twitch login name Channel to join (required)
theme 31 values, listed in full at /docs#themes Color theme preset (default wolf)
variant theme-specific (e.g. theme=terminal&variant=amber) Color variation of the chosen theme; unknown values fall back to the theme default
layout inline, stacked Name inline with the message, or on its own line above it
align left, right Which edge messages hug; under scroll=ticker, which way the lane travels
group true, false Consecutive messages from one chatter share a single header
scroll off, ticker Stacked column, or one horizontal lane sliding right to left
scrollspeed 1 to 5, whole steps (default 1) Ticker lane speed; ignored unless scroll=ticker
bg off, panel, bubble Display mode (default off). panel draws its backdrop only while there are messages
size percent, 50 to 300 (default 100) Scales theme text, with a 12px rendered floor
emotescale 1 to 4, half steps (default 1) Grows emotes on messages that are nothing but emotes
max 1 to 200 (default 50) Max messages kept on screen
hidebots flag Hide known chat bots (Nightbot, etc.)
hide comma-separated logins Always hide these users
allow comma-separated logins Featured mode: only show these users
hidecommands flag Hide messages starting with !
delay seconds, 0 to 300 (default 0) Hold non-mod messages so deletions land before display
badges false to disable (default on) Badge icons before names
pronouns flag Pronoun badge before names (via pronouns.alejo.io)
avatars off, all, subs (default off) Profile pictures before names (via api.ivr.fi). subs only looks up subscribers and founders
events comma-separated sub, cheer, raid, first, announce, or all Show sub, gift, cheer, raid, first-message and announcement rows (default none)
timestamps flag HH:MM before each message
animate false to disable (default on) Slide/fade entrance animation
media animated, static (default animated) Static art avoids continuous decode and repaint
fade seconds, 0 to 600 (default 0) Auto-hide each message N seconds after it appears
badgeart comma-separated set=url or set/version=url pairs Custom badge art overriding the Twitch defaults
badgegist public gist id or URL Custom badge art hosted in a gist (same pairs, one per line, or a JSON map)
refresh minutes, 0 or 1 to 1440 (default 0) Re-fetch channel art every N minutes; 1-4 round up to 5; globals retain their TTL

Invalid or missing values fall back to safe defaults; a typo in OBS never produces a blank overlay.

Events ride the same anonymous connection the chat does, so events needs no account: subs, gifts, raids and cheers all arrive as ordinary IRC traffic. Follows are the exception, since they only exist on EventSub. A sub or raid renders as a whole sentence with no separate name header; a cheer, first message or announcement decorates the message it arrived with.

Custom badge art precedence, weakest to strongest: fetched Twitch art, then badgegist, then inline badgeart. A bare set key (no /version) covers every version of that set. The gist is fetched from the public GitHub API (no token), which allows 60 unauthenticated requests per hour per IP. Refresh is off by default; when enabled, a value of 1 to 4 rounds up to the 5-minute floor rather than falling back to off, which keeps a gist well under that limit. The art URLs in badgeart and badgegist point at whatever image host you name, and your browser fetches them directly. Only HTTPS URLs are accepted (URLs carrying credentials are rejected), and badge, emote, and avatar images load with a no-referrer policy so the overlay URL is not sent to those hosts.

In OBS 31 or newer, add a Browser source with the generated URL and set Width and Height on the source itself (try 480 x 800). Leave "Shutdown source when not visible" and "Refresh browser when scene becomes active" off.

Tech Stack

Layer Technology
Framework React 19 + TanStack Router (Vite)
Language TypeScript (strict)
Chat @twurple/chat (anonymous IRC)
Emotes 7TV, BTTV, FrankerFaceZ public APIs
Badges api.ivr.fi (Twitch badge art)
Pronouns pronouns.alejo.io (opt-in)
Avatars api.ivr.fi (batched, opt-in)
Cheermotes static-cdn.jtvnw.net (global tiers)
Styling Tailwind CSS 4 + CSS variables
UI shadcn/ui primitives (packages/ui)
Monorepo Turborepo + Bun workspaces
Linting Biome
Deploy GitHub Pages (static)

Development

Prerequisites

  • Bun 1.3 or newer
  • OBS Studio 31 or newer (for overlay testing)

Setup

  1. Install dependencies:

    bun install
  2. Run the web dev server:

    bun run dev:web

Development Scripts

  • bun run dev: Start all apps in development mode
  • bun run dev:web: Start only the web app (port 3001)
  • bun run build: Build the static site to apps/web/dist
  • bun run check-types: Check TypeScript types across the monorepo
  • bun run check: Run Biome formatting and linting

Code Quality

  • TypeScript strict mode across every workspace
  • Biome for linting and formatting
  • Turborepo task caching for fast builds
  • hb-* class names on overlay elements are a public contract for OBS Custom CSS overrides; keep them stable

Deployment

GitHub Pages (default)

Pushes to main build and deploy automatically via .github/workflows/deploy.yml. One-time setup: in the repository settings, set Pages > Source to "GitHub Actions". The site serves at https://mrdemonwolf.github.io/howlbox/ (the build sets BASE_PATH=/howlbox/; use a custom domain and drop the variable for root hosting).

The build generates a 404.html marked noindex plus a real index.html per route (including /overlay), so every route resolves with an HTTP 200 instead of falling back to the SPA's 404 status.

Coolify or any static host

bun run build produces a fully static site in apps/web/dist. Serve that folder as-is (set BASE_PATH at build time if hosting under a subpath). No server runtime is required.

Test URLs

Once deployed, these are ready to paste into an OBS browser source (swap the channel for testing against a busier chat):

https://mrdemonwolf.github.io/howlbox/overlay?channel=mrdemonwolf&theme=wolf&bg=off&hidebots=true
https://mrdemonwolf.github.io/howlbox/overlay?channel=mrdemonwolf&theme=glass&bg=bubble&fade=30
https://mrdemonwolf.github.io/howlbox/overlay?channel=xqc&theme=terminal&bg=panel&timestamps=true

Suggested source size: 480 x 800 at the default font scale.

Project Structure

howlbox/
├── apps/
│   └── web/
│       └── src/
│           ├── components/
│           │   ├── chat/      # Overlay renderer + theme CSS variables
│           │   └── landing/   # Landing demo + /config URL builder
│           ├── hooks/         # Chat connection, emote/badge loading
│           ├── lib/
│           │   ├── emotes/    # 7TV/BTTV/FFZ fetch, cache, resolution
│           │   ├── overlay/   # URL param schema + builder
│           │   └── twitch/    # Anonymous chat client, badges, colors
│           └── routes/        # / landing, /config builder, /docs reference, /overlay
├── packages/
│   ├── config/                # Shared tsconfig base
│   └── ui/                    # Shared shadcn/ui components and styles
├── .github/workflows/         # CI deploy to GitHub Pages
├── biome.json                 # Lint and format config
└── turbo.json                 # Turborepo pipeline

License

GitHub license

Contact

Have questions or feedback?

Made with love by MrDemonWolf, Inc.

About

Self-hosted Twitch chat overlay for OBS with native, 7TV, BTTV, and FFZ emotes, built with React, Vite, Twurple, and Tailwind CSS

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages