A self-hosted stream overlay toolkit — built around a cinematic credits roll that recognizes the people who make your stream what it is: subscribers, followers, cheerers, raiders, gifters, and chatters.
StreamPulse started as a way to give every community member their moment in the spotlight at the end of a stream. It grew into a full data toolkit with live stats, session history, searchable chat logs, hashtag tracking, highlights, and more — all powered by SocialStream Ninja and the Twitch API.
Hashtags are a fun way to capture community moments in smaller streams — viewers drop
#blessedor#teamwipeand they show up live on the overlay and in the credits. For larger communities, you'll want to use the built-in moderation tools (ban/purge) or disable hashtags entirely unless you have a solid moderation process.
StreamPulse runs on Node.js. Download and install the LTS version (v18 or newer):
- Mac: Download the
.pkginstaller from nodejs.org and double-click to install - Windows: Download the
.msiinstaller from nodejs.org and run through the setup wizard
To verify it's installed, open Terminal (Mac) or Command Prompt (Windows) and type:
node --versionYou should see something like v20.x.x.
Go to the Releases page and download the Source code (zip) from the latest release.
- Unzip the downloaded file
- Move the folder somewhere convenient (e.g. your Documents folder)
- Rename it to
streampulseif you'd like
Before starting, you'll need a Twitch Application and SocialStream Ninja configured (see Prerequisites below).
Open the streampulse folder and:
- Make a copy of
config.example.jsonand name itconfig.json - Open
config.jsonin any text editor and fill in your credentials:broadcaster_id— Your Twitch numeric ID (look it up at streamscharts.com/tools/convert-username)broadcaster_name— Your Twitch usernameclient_idandclient_secret— From your Twitch application (see Prerequisites)session_id— Your SSN Session ID
Open Terminal (Mac) or Command Prompt (Windows), then navigate to your StreamPulse folder:
cd ~/Documents/streampulseWindows tip: You can also type
cmdin the File Explorer address bar while inside the folder to open a Command Prompt there.
Install dependencies (only needed the first time, or after updates):
npm installInstall the bundled Chrome used for PDF exports on this machine:
npm run install:chromeStart the server:
npm startOn first run, a browser window opens for Twitch authorization. After that, the server handles everything automatically.
Add Browser Sources in OBS with these URLs:
- Credits:
http://localhost:3000/credits.html - Stats:
http://localhost:3000/stats.html - Hashtags:
http://localhost:3000/hashtags.html - Music:
http://localhost:3000/music.html
Management pages (open in your browser, not OBS):
- Dashboard:
http://localhost:3000/dashboard.html - Sessions:
http://localhost:3000/sessions.html - Highlights:
http://localhost:3000/highlights.html - Config:
http://localhost:3000/config-editor.html - Music Editor:
http://localhost:3000/music-editor.html
StreamPulse requires two external services to collect live stream data. Set both up before installing.
SSN captures live chat messages, subscriptions, follows, raids, bits, and donations from Twitch (and YouTube, Kick, etc.) and forwards them to StreamPulse via WebSocket.
Install & Configure:
- Install SocialStream Ninja — available as a browser extension or a standalone desktop app
- Open SSN settings and go to Global Settings → Mechanics
- Enable Toggle 1 (Enable remote API control)
- Enable Toggle 3 (Send chat messages to API server)
- Note your Session ID — visible in the
?session=parameter of your dock.html or featured.html URL - Keep the SSN dock page open during your stream (browser tab or standalone app)
Tip: You can test the connection using SSN's API Sandbox — connect with your Session ID to see live messages.
A Twitch app provides subscriber, follower, and bits data via the Twitch API.
Create your app:
- Go to dev.twitch.tv/console/apps and create a new application
- Set the OAuth Redirect URL to
http://localhost:3000/auth/callback - Note your Client ID and Client Secret
- Bitfocus Companion — Trigger API endpoints via Stream Deck buttons
- OBS Studio — For displaying browser source overlays
- Credits Roll — Cinematic scrolling credits with subscribers, followers, chatters, emotes, hashtags, raids, gift subs, cheerers, and more
- Music Overlay — "Now Playing" overlay for Apple Music, Spotify, and VLC with album art, marquee titles, and multiple display modes
- Live Stats Overlay — Persistent top chatters, emotes, and hashtags across sessions
- Session History — Browse archived sessions with full chat logs, searchable with boolean operators (
AND,OR,"exact phrase",user:name) - Highlights — Pin notable chat messages and export them per session
- Chat Log Exports — Export filtered chat logs and highlights as TSV, TXT, or PDF (with per-user colored usernames and emote images)
- Hashtag Tracking — Live hashtag overlays with moderation (ban/unban/purge)
- Dashboard — Server status, session stats, message volume chart, and quick actions
- Fully Configurable — All sections, titles, social links, and options editable via web UI or
config.json - Twitch OAuth — Browser-based authorization with automatic token refresh
- WebSocket Push — Live data pushed to overlays in real-time
- Session Lifecycle — End/start session endpoints for Companion integration
- Backup & Restore — Download full data backups as ZIP, restore from backups
- Discord Webhooks — Optional notifications for raids, subs, donations, bits, and follows
- Preview Mode —
?preview=truerenders credits without scrolling for layout testing
┌─────────────┐ ┌──────────────────────────────────────────┐
│ SSN Dock │────▶│ server.js │
│ (browser) │ WSS │ ┌─────────────┐ ┌──────────────────┐ │
└─────────────┘ │ │ SSN Collect │ │ Twitch API Fetch │ │
│ │ (WebSocket) │ │ (auto-refresh) │ │
│ └──────┬──────┘ └────────┬─────────┘ │
│ │ writes │ writes │
│ ▼ ▼ │
│ data/chat.json data/subs.json │
│ data/stats.json data/bits.json │
│ data/followers.json│
│ ┌─────────────┐ ┌──────────────────┐ │
│ │ HTTP Server │ │ WebSocket Server │ │
│ └──────┬──────┘ └────────┬─────────┘ │
└─────────┼──────────────────┼─────────────┘
│ serves │ pushes live data
┌───────────────┼─────────┐ │
▼ ▼ ▼ ▼
┌──────────────┐ ┌──────────┐ ┌──────────────────┐
│ credits.html │ │stats.html│ │ dashboard.html │
│ (OBS source) │ │(OBS src) │ │ sessions.html │
└──────────────┘ └──────────┘ └──────────────────┘
SSN detects these events via WebSocket:
- Chat messages (all platforms)
- Subscriptions:
new_subscriber,resub,subscription_gift - Follows:
follow,new_follower - Raids:
raid - Bits/Cheers: via
hasDonationfield containing "bit" - Donations: via
hasDonationfield - Emotes and hashtags: parsed from chat messages
Copy config.example.json to config.json and fill in your credentials:
{
"port": 8080,
"broadcaster_id": "YOUR_BROADCASTER_ID",
"broadcaster_name": "YOUR_TWITCH_USERNAME",
"twitch": {
"client_id": "YOUR_TWITCH_CLIENT_ID",
"client_secret": "YOUR_TWITCH_CLIENT_SECRET"
},
"ssn": {
"session_id": "YOUR_SSN_SESSION_ID",
"server": "wss://io.socialstream.ninja"
}
}All other settings can be edited live via the Config Editor — no restart needed.
| Option | Type | Default | Description |
|---|---|---|---|
port |
number | 8080 |
HTTP server port |
broadcaster_id |
string | Your Twitch numeric broadcaster ID | |
broadcaster_name |
string | Your Twitch username (filtered from sub/follower lists) | |
twitch_refresh_minutes |
number | 10 |
Auto-refresh interval for Twitch API data |
days_filter |
number | 30 |
Only show followers from last N days |
active_subs_only |
boolean | false |
Only show subscribers who chatted this stream |
exclude_users |
array | [] |
Usernames to exclude from all data (case-insensitive) |
banned_users |
array | [] |
Usernames completely hidden from everything |
hashtags_enabled |
boolean | true |
Enable hashtag tracking |
chat_log_enabled |
boolean | true |
Enable chat log recording |
auto_backup_on_session_end |
boolean | false |
Auto-backup data when ending a session |
music.enabled |
boolean | false |
Enable music "Now Playing" overlay |
music.source |
string | apple_music |
Music source: apple_music, spotify, or vlc |
music.poll_seconds |
number | 5 |
How often to check for track changes |
Credits sections, social links, and the special thanks section are all configurable via the Config Editor or directly in config.json under the credits key. Each section supports enabled, title, and subtitle.
Customize the look of all overlays (credits, stats, hashtags) from the Config Editor under Overlay Theme:
- Font — Choose from popular Google Fonts or enter any custom Google Font name
- Text / Accent Colors — Color pickers with manual hex/rgb input
- Background — Set to
transparentfor OBS (default), or pick a color for previewing - Text Outline — Toggle the shadow outline on/off, pick outline color
- Font Scale — Scale all overlay text proportionally (0.5× – 2×)
Optional webhook notifications for stream events:
{
"webhooks": {
"enabled": true,
"discord_url": "https://discord.com/api/webhooks/...",
"events": ["raid", "subscribe", "donation", "bits", "follow"],
"batch_seconds": 5
}
}| Parameter | Default | Description |
|---|---|---|
duration |
82 |
Scroll duration in seconds |
speed |
Speed multiplier (only if duration not set) |
|
days |
config value | Override days_filter from config |
preview |
false |
Show all credits without scrolling |
🎵 Syncing credits with music: Set
?duration=to match your end-of-stream track length so the credits scroll finishes exactly when the song ends. For example,?duration=75for a 1:15 track. Use a Companion/StreamDeck button to trigger both the OBS credits source and music simultaneously for a clean outro.
| Parameter | Default | Description |
|---|---|---|
days |
all time | Only show stats from last N days |
date |
Single date (YYYY-MM-DD) |
|
from / to |
Date range | |
limit |
20 |
Top N items per column |
refresh |
60 |
Auto-refresh interval in seconds |
| Endpoint | Description |
|---|---|
GET /api/status |
Server health, SSN connection, data counts |
GET /api/config |
Current config |
PUT /api/config |
Update config (hot-reload) |
GET /api/fetch |
Trigger Twitch API refresh |
GET /api/reset |
Clear session chat data |
GET /api/end-session |
Archive session + reset |
GET /api/start-session |
Start new session |
GET /api/shutdown |
Archive + graceful shutdown |
GET /api/chat |
Current session data (live) |
GET /api/chat-log |
Current session chat log |
GET /api/chat-log/search |
Cross-session search (?q=, ?user=, ?type=, ?session=) |
GET /api/chat-log/export |
Export chat log (?format=tsv|txt|pdf, ?q=, ?type=) |
GET /api/stats |
Persistent stats (daily buckets) |
GET /api/sessions |
List archived sessions |
GET/POST/DELETE /api/highlights |
Pin/unpin/list highlights |
GET /api/highlights/export |
Export highlights (?format=, ?session=, ?q=) |
GET/POST/DELETE /api/hashtags/banned |
Hashtag moderation |
GET /api/export |
Stats CSV export (?type=chatters|emotes|all) |
GET /api/backup |
Download full data backup (ZIP) |
GET /auth/twitch |
Start Twitch OAuth flow |
GET /api/music/now-playing |
Current track info (JSON) |
GET /api/music/artwork |
Current album art image |
ws://localhost:3000 |
WebSocket — live data push |
Use the Generic HTTP module:
| Action | URL |
|---|---|
| Refresh Twitch data | GET http://localhost:3000/api/fetch |
| End session | GET http://localhost:3000/api/end-session |
| Start new session | GET http://localhost:3000/api/start-session |
| Shutdown server | GET http://localhost:3000/api/shutdown |
| File | Lifecycle | Contains |
|---|---|---|
data/chat.json |
Cleared on startup (archived) | Session chatters, subs, emotes, hashtags |
data/stats.json |
Persists across restarts | Cumulative stats with daily buckets |
data/sessions/ |
Persists | Archived session data + JSONL chat logs |
data/highlights.json |
Persists | Pinned chat messages |
data/subs.json |
Refreshed from Twitch API | Subscriber list |
data/bits.json |
Refreshed from Twitch API | Bits leaderboard |
data/followers.json |
Refreshed from Twitch API | Follower list |
data/.twitch-token.json |
Persists | OAuth tokens |
Data is saved to disk every 5 seconds and on graceful shutdown (Ctrl+C).
streampulse/
├── server.js # Unified server (HTTP + WebSocket + SSN + Twitch)
├── config.json # Your config and credentials (git-ignored)
├── config.example.json # Template config
├── credits.html/css/js # Credits overlay (OBS browser source)
├── stats.html # Stats overlay (OBS browser source)
├── hashtags.html # Hashtag overlay (OBS browser source)
├── music.html # Music "Now Playing" overlay (OBS browser source)
├── music-editor.html # Music overlay customization
├── music-url-wizard.html # Music URL builder
├── dashboard.html # Dashboard UI
├── sessions.html # Session history + chat logs
├── highlights.html # Highlights viewer
├── categories.html # Stream categories viewer
├── config-editor.html # Live config editor
├── backup.html # Backup & restore
├── manage-hashtags.html # Hashtag moderation
├── api.html # API reference
├── docs.html # Documentation
├── nav.js # Shared navigation
├── rebuild-session.js # Utility: rebuild session from JSONL
└── data/ # Generated data (git-ignored)
- SSN dock page must be open in a browser tab
- Ensure Toggle 1 and Toggle 3 are enabled in SSN Global Settings → Mechanics
- Verify
session_idinconfig.jsonmatches the?session=value in your SSN dock URL - Check
http://localhost:3000/api/status—ssn.connectedshould betrue - Test with the SSN API Sandbox to verify messages are flowing
- Visit
http://localhost:3000/auth/twitchto re-authorize - Ensure
http://localhost:3000/auth/callbackis registered as an OAuth Redirect URL - Verify
client_idandclient_secretinconfig.json
- Ensure
npm startis running - OBS URL:
http://localhost:3000/credits.html - Right-click OBS source → "Refresh cache of current page"
- Puppeteer's browser download is machine-specific
- Run
npm run install:chrome - Restart StreamPulse with
npm start - If needed, reinstall dependencies first with
npm install
config.jsoncontains credentials — git-ignored, never commit- OAuth tokens stored locally in
data/.twitch-token.json— git-ignored - Server only listens on localhost
- SocialStream Ninja by Steve Seguin
- Twitch API
- OBS Studio
- Puppeteer for PDF exports
- Font Awesome for icons
- Jersey 20 Google Font