Skip to content

Repository files navigation

PokeTeamStream

Webapp and stream overlay for displaying and remotely updating a Pokemon team roster, connected peer-to-peer over WebRTC.

Two parts work together:

┌────────────┐   websocket    ┌───────────────┐   websocket    ┌───────────────────┐
│   webapp   │ ─────────────► │ signal server │ ◄───────────── │  overlay (OBS or  │
│  (remote)  │                └───────────────┘                │  SE custom widget)│
│            │ ◄════════ WebRTC data channel (P2P) ══════════► │                   │
└────────────┘                                                 └───────────────────┘
  • Webapp (packages/webapp) — the streamer's remote control: search any Pokemon (via PokeAPI), pick an appearance (official artwork, per-game sprites, Home renders, shiny variants), then drag & drop (or tap-to-assign) onto a six-slot roster. Layout controls (row / column / grid / staggered arrangements, spacing, stagger, per-slot scale and offsets) update the on-stream overlay live, with a WYSIWYG 16:9 preview.
  • Overlay (packages/widget) — shows the team on stream. Two flavors from one codebase: a StreamElements custom widget (state persisted in the SE store) and a standalone OBS browser source (state persisted in localStorage, configured entirely by URL).
  • Shared (packages/shared) — protocol types, team-state model/migration, and the layout math both sides render with.

The webapp and overlay pair through a lightweight websocket signal server and then talk directly over an encrypted WebRTC data channel. Auth is password-based, with self-signed JWTs issued by the overlay for passwordless reconnects (changing the password invalidates outstanding tokens). The connection self-heals: heartbeat, automatic reconnection with backoff, and signal-server reconnection on the overlay side.

Local development

Requires Node 22+.

npm install

# Terminal 1: local signal server (stand-in for webrtc-ws-server)
npm run signal-server

# Terminal 2: overlay dev server (http://localhost:5173)
npm start -w packages/widget

# Terminal 3: webapp dev server (http://localhost:5174)
npm start -w packages/webapp -- --port 5174

Then:

  1. Open the widget dev harness (mocks the StreamElements environment): http://localhost:5173/dev/?username=devchannel&password=test — or the standalone overlay: http://localhost:5173/overlay/?c=devchannel&s=test
  2. Open the webapp and connect with username devchannel, password test.

In dev builds the signal server defaults to ws://localhost:8080; set VITE_SIGNAL_SERVER to override.

Checks: npm run lint, npm test, npm run build.

Building for deployment

Due to the nature of WebRTC communications, this project requires a deployment of a websocket signal server to pair peers. Specifically, this project has been made using webrtc-ws-server. Ensure such a server is deployed and can be accessed.

Once a signal server is live, with the appropriate environment variable VITE_SIGNAL_SERVER=wss://signalserver set, run:

npm install
npm run build
  • Webapp: ./packages/webapp/build
  • SE widget script: ./packages/widget/build
  • Standalone overlay: ./packages/widget/build/overlay

The GitHub Pages workflow (.github/workflows/deploy.yml) deploys the webapp at the site root with the widget at /widget/ and the overlay at /widget/overlay/ (the VITE_SIGNAL_SERVER repository secret must be configured).

Environment variables

Variable Required Purpose
VITE_SIGNAL_SERVER production builds websocket signal server address
VITE_ICE_SERVERS no comma-separated ICE server list (defaults to Google STUN)
VITE_OVERLAY_URL no overlay base URL used by the webapp's Overlay Setup dialog
VITE_WIDGET_URL no widget assets base URL used for StreamElements snippet generation (defaults to <origin>/widget/)
VITE_MAX_TOKEN_LIFE no auth token lifetime in ms (default 24h)

Getting set up

The easiest way: open https://poketeam.stream and click New here? Set up your overlay on the login screen. The wizard walks you through StreamElements or OBS setup with copy-paste snippets, then verifies the connection live — you land in the app already connected.

The manual steps below are the offline fallback.

StreamElements (manual)

  1. Within StreamElements, add a Custom widget (found within the Static / Custom section).
  2. With the empty custom widget selected, select OPEN EDITOR from the left side menu.
  3. Under HTML, highlight and delete any default content, then copy & paste the following:
<script type="module" src="https://poketeam.stream/widget/poke-team-stream-widget.js"></script>
<link rel="stylesheet" href="https://poketeam.stream/widget/poke-team-stream-widget.css">
  1. Under CSS and JS, highlight and delete any default content. These should be empty.
  2. Under FIELDS, highlight and delete any default content, then copy & paste the following:
{
  "password": {
    "label": "Set a password for website access",
    "type": "password",
    "value": ""
  }
}
  1. Under DATA, highlight and delete any default content, then copy & paste {}.
  2. Save with DONE, then fill out the new field on the left side menu:
    • Set a password for website access — anything you like; it's the password you'll use on the website, tied to your Twitch channel name. It's stored within StreamElements storage and not sent to any third parties.

Note: substitute https://poketeam.stream for your deployed webapp/widget server URL as needed.

OBS, no StreamElements (manual)

  1. In the webapp, use the onboarding wizard's OBS path — or, once connected, the menu (⋮) → Overlay setup.
  2. Enter your channel name, generate (or choose) a secret, and copy the browser source URL.
  3. In OBS: add a Browser source, paste the URL, set 1920×1080. The background is transparent.
  4. Connect from the webapp with your channel name + that secret.

Run either the StreamElements widget or the OBS overlay for a given channel — not both at once (they pair under the same key).

Testing

Unit tests (npm test, vitest) cover the shared state migration, layout math, message parsing, and the JWT auth flow. The manual end-to-end checklist lives in docs/testing.md.

About

Webapp and StreamElements widget for displaying and remotely updating Pokemon team roster via WebRTC.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages