Skip to content

WattRoom

Train together, not alone.

Discord for indoor cycling — structured workouts your whole crew rides at once, with voice, camera, game modes and a shared jukebox. No virtual world: your watts are the game.

License: AGPL-3.0 Go Svelte 5 LiveKit

Architecture · Spec · Founding doc · Contributing · built by Natron

Like the idea? Star the repo — it helps other pain-cave dwellers find it.

A live WattRoom session: six riders on a threshold block, each rider's watts, w/kg and execution score on one dashboard next to the interval timeline and the chat

Six riders, one timeline. Every target scales to the rider's own FTP, so the crew rides together whatever their numbers are.

Why

Indoor training is boring alone. Zwift fixes that with a game world; WattRoom fixes it with presence — you hop into your crew's voice channel with your training buddies, everyone rides the same workout scaled to their own FTP, you talk, you see each other, you share music. A group ride for pain caves.

What's inside

🚴 Crews — text and voice channels, live watts, HR and cadence on one dashboard in a session, voice & camera one tap away 📈 Structured workouts — curated library + editor, precise ERG control over BLE FTMS
🎮 Seven game modes — sprint klaxons, eliminations, Watt Golf, Backyard Ramp, … 🎵 Shared jukebox — one synced YouTube soundtrack per voice channel
🏅 Rides that count — every session saved, .fit export, Strava upload, XP & trophies 🔒 Private by default — metrics stay in the session, AV never recorded

Screens

The sprint moment The workout library
A sprint moment: riders ranked live by w/kg The workout library, every target scaled to your FTP

The way in — on a desk, and on the phone that lives on the bars:

WattRoom landing page WattRoom on a phone

Quick start (dev)

Requirements: Go 1.26+, Node 22+, pnpm, Docker. The pnpm version is pinned in web/package.json and desktop/package.json (packageManager); pnpm 10 and newer, and corepack, install that version for you, so there is nothing to match by hand.

make infra        # Postgres + LiveKit (dev mode) in containers
make dev-server   # terminal 1: Go server with hot reload on :8080
make dev-web      # terminal 2: Vite dev server on :5174 (proxies /api + /ws)

No smart trainer needed — the simulated trainer covers development, and /dev/channel is a full mock voice channel. See CONTRIBUTING.md.

Hardware & browsers

A smart trainer speaking BLE FTMS (pre-FTMS Wahoo units are backlog, #4), talked to directly from the browser via Web Bluetooth — which is Chromium-only: Chrome/Edge on desktop and Android. No iOS training path (Safari won't implement Web Bluetooth — a researched decision, not an oversight); a crew's channels open in any browser, with the affordances that need a trainer gated off rather than a separate read-only page.

Stack

Go server (in-memory live hub, one goroutine per voice channel) · SvelteKit SPA · PostgreSQL · self-hosted LiveKit · single binary with embedded frontend, deployed as one compose stack on a single VM. Every product and architecture decision is recorded in WATTROOM.md and docs/decisions/; the research behind them in docs/RESEARCH.md.

Releases

WattRoom ships several times a day: cutting a release is cheap, not because every change is urgent. A release only ever adds a small, already-merged change, and rolling one back is just repointing the running image at the previous tag — the database is never touched. See ADR-0019 for the full mechanism.

License

AGPL-3.0 — © Natron

About

Train together, not alone. Collaborative indoor cycling: structured workouts, FTMS trainer control, crews with voice channels, live metrics, camera and a synced jukebox.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

7 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages