BikeControl (SwiftControl)
Use Zwift Click, Zwift Play, Shimano Di2, or any Bluetooth controller with MyWhoosh, Rouvy, Zwift, and more. Free to try on iOS, Android, Windows, and macOS.
Discord for indoor cycling — no virtual world, your watts are the game.
Sports & fitnessTypeScript · GoGitHub @natrontechOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Train together, not alone. Collaborative indoor cycling: structured workouts, FTMS trainer control, shared rooms with live metrics, voice, camera and a synced jukebox.
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
Discord for indoor cycling. Your crew rides one structured workout together,
every smart trainer on its own rider's FTP, with voice built in.
No virtual world: your watts are the game.
Indoor training is boring alone, and riding with friends usually means three
apps: a training app, Discord for voice, and something for music, all
fighting over one headset. Zwift answers boredom with a game world.
WattRoom answers it with your crew:Read the full README ↗Discord for indoor cycling. Your crew rides your own roads in a 3D world, or one structured workout with every smart trainer on its own rider's FTP. Voice is built in, so you talk the whole way.
Ride now at wattroom.ch · Desktop app · Game modes · Self-host · Contribute
Indoor training is boring alone, and riding with friends usually means three apps: a training app, Discord for voice, and something for music, all fighting over one headset. Zwift answers boredom with a game world. WattRoom answers it with your crew:
Workouts on the road. Ride a workout on one of your roads and its next three blocks are painted on the asphalt, each with its name and your target. A sprint gets a banner across the road from 1 km out.
Or on the graph. A workout without a road rides on its interval graph,
every block labelled. The library, an editor and .zwo and .erg import fill
the shelf, and a free ramp test finds your FTP.
Your ghost. Ride a road of yours again from its start and the rider you were last time rides beside you, a see-through figure in your own kit. The bike computer says the gap in words.
Gears and your phone. Easier and Harder shift virtual gears on a road,
from the screen, the − and + keys or a Zwift Cog. Open WattRoom on your
phone while the desk rides and the phone becomes your remote.
Races on your roads. Pick a road in the session picker, tap Race it, and choose Race, Last Light or Wheelrace. Races run on W/kg, with results by category on the closing card.
Seven game modes, decided by watts alone and measured on each rider's own FTP, so the smallest engine in the crew can win.
Every ride saves privately, with a .fit file to download and one tap to
Strava. Voice and video are never recorded.
| Mode | How it plays |
|---|---|
| Sprint Roulette | Five sprints land at random, a klaxon three seconds before each. |
| Points Race | Two-minute intervals with sprints hidden in them. Every one scores. |
| Watt Golf | Hit a wattage for ten seconds, with the meter turned off. |
| Backyard Ramp | Three-minute rounds, +5 % FTP each. Ten seconds below and you're out. |
| Collective Ramp | The same, on the crew's average. Nobody gets dropped alone. |
| Floor is Lava | A power zone is called. Leave it and you burn a life. |
| Team Relay | One rider on the front at 110 %, everyone else recovering. |
Races on a road start from the session picker: Race, Last Light (10, 20 or 30 minutes) and Wheelrace (a par of 15 to 45 minutes). The parameters live in docs/spec/game-modes.md. You can try a sprint on the website.
[!NOTE] Hardware and browsers. WattRoom needs a smart trainer that speaks Bluetooth FTMS, which most current trainers do. Pre-FTMS Wahoo units are not supported yet. It also needs Chrome or Edge on Windows, macOS or Android, or the desktop app. On Linux, Chrome keeps Web Bluetooth behind a flag. Safari and Firefox cannot reach a trainer, so iPhone and iPad riders can join the crew and the call but not ride. That is a researched decision, not an oversight.
| WattRoom | Zwift | TrainerRoad | MyWhoosh | |
|---|---|---|---|---|
| Price | Free | US$19.99/mo | US$21.99/mo per rider | Free |
| One workout, each on own FTP | ✓ anyone in the channel starts it | ✓ via a Meetup | ✓ up to 11 riders | pacer-led group workouts |
| Voice built in | ✓ | text chat | ✓ voice and video | text chat |
| 3D world | your own roads | ✓ | none | ✓ |
| Runs in a browser | ✓ | – | – | – |
| Open source | ✓ AGPL | – | – | – |
Checked September 2026. There are sources and a "pick them if…" for each on wattroom.ch/zwift-alternative. We make WattRoom, so check for yourself.
mkdir -p /opt/wattroom && cd /opt/wattroom
# copy this repository's deploy/ directory here
cp .env.example .env # every value is explained inside
cp livekit.yaml.example livekit.yaml # same keys as .env
docker compose -f docker-compose.prod.yml up -d
Releases are CalVer tags (ghcr.io/natrontech/wattroom:2026.09.1). An update
is a tag bump, and a rollback is the previous tag: migrations only ever add
(ADR-0019).
The full guide, including how LiveKit reaches the server and what to back up,
is in deploy/README.md.
Requirements: Go 1.26+, Node 22+, pnpm, Docker. The pnpm version is pinned in
web/package.json (packageManager), and pnpm 10+ or corepack installs it for you.
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. make site-screens redraws the
screenshots in this README and on the landing from the design shots, and
make screenshots redraws the share cards and the other pages' screenshots
from the running dev pair. Start with
CONTRIBUTING.md; every product and architecture decision is
in WATTROOM.md and docs/decisions/.
flowchart LR
subgraph Browser["Browser (Chrome / Edge)"]
SPA["SvelteKit SPA<br/>+ prerendered public pages"]
end
Trainer(["Smart trainer<br/>BLE FTMS"]) <-- Web Bluetooth --> SPA
SPA <-- "REST + WebSocket" --> Server["Go server<br/>live hub in memory"]
SPA <-- WebRTC --> LiveKit["LiveKit SFU<br/>voice + camera"]
Server --> PG[("PostgreSQL<br/>durable data only")]
SPA -. "YouTube IFrame" .-> YT(["Jukebox"])
The seams are deliberate. The browser owns the trainer, the server owns live state in memory, and Postgres owns only what has to last (docs/ARCHITECTURE.md). WattRoom ships several times a day: a release only ever adds a small, merged change, and rolling back means repointing the image at the previous tag.
AGPL-3.0, © Natron, built in Switzerland. If WattRoom made a Tuesday night better, star the repo. It helps other pain-cave dwellers find it.