# KICKR CORE 2 Hub

> An indoor cycling cockpit with virtual shifting, a 3D riding world, live trainer telemetry, and game-style progression.

Canonical page: [KICKR CORE 2 Hub](<https://devanmetz.com/portfolio/kickr-core-hub/>)

Project date: Aug 2026

Updated: 2026-10-13

Category: Cycling software

Status: Interactive prototype

Tags: React, TypeScript, Three.js, Smart trainers

- **My work:** Trainer integration, 3D interface, and ride analytics
- **Stack:** React, TypeScript, Three.js, and Node.js
- **Hardware target:** Wahoo KICKR CORE 2 via Direct Connect

- [Try the simulator](<https://kickr-core-hub.pages.dev/>)

## In short

I built KICKR CORE 2 Hub as an indoor cycling interface with virtual gears, a moving 3D world, ride statistics, and game progression. Its browser simulator lets anyone explore those features without a trainer. Controlling a physical Wahoo trainer requires a local connection service, and the project remains an interactive prototype.

![A cyclist in a colorful 3D landscape surrounded by power, cadence, virtual gearing, and ride timeline panels.](<https://devanmetz.com/_astro/kickr-core-hub.D8EbYecQ_ZOmNAa.webp>)

The browser simulator running an endurance ride. All telemetry shown here is synthetic.

## Overview 

I built KICKR CORE 2 Hub to turn indoor cycling into an interactive riding cockpit.

It combines an interface for a smart trainer (an indoor cycling trainer that reports ride data and accepts control commands), virtual gears, a Three.js 3D world, and saved game progression in one browser user interface.

The project spans both sides of the connection: a Node.js bridge (a local connection service) for communicating with a Wahoo trainer over the local network, and a React interface for riding, reviewing sessions, and experimenting with different setups.

The [public demo](<https://kickr-core-hub.pages.dev/>) includes a simulator that runs without trainer hardware.

## Riding interface 

The main view puts power, cadence (pedaling rate), speed, distance, and accumulated work (energy over the ride) around a moving 3D scene. Short power averages and a scrolling timeline make changes in effort visible without opening another panel.

### The riding world 

Pedaling animation follows cadence, while the landscape, visual effects, and speed streaks respond to the ride. The world includes rolling terrain, pine trees, mountain ridges, and streetlights.

-   **Camera views:** chase, first-person, drone, and free-orbit.
-   **Lighting:** dawn, daytime, sunset, and night change the atmosphere.

The aim is to make the workout readable while giving the rider something more engaging than a stationary dashboard.

## Virtual shifting and trainer controls 

Virtual gearing changes the simulated gear without a physical shift. It is designed for a single-cog trainer setup, with one rear sprocket. Presets include:

-   A sequential 24-speed drivetrain, stepping through gears in order.
-   Shimano 2×12 and SRAM AXS 2×12 setups, each with two front gears and twelve rear gears.
-   A 1×12 gravel setup, with one front gear and twelve rear gears.

Riders can shift with the on-screen controls, keyboard, or a gamepad. Mechanical shift sounds provide another cue that a gear changed.

### Trainer control modes 

The trainer-control interface supports four modes:

-   **ERG (target-power mode):** hold a target power.
-   **Simulation:** configure grade (slope), wind, rolling resistance (drag from tire contact), and aerodynamic conditions (air drag).
-   **Resistance:** set a resistance percentage directly.
-   **Level:** select a progressive resistance level from 0–9.

### Connecting to a trainer 

The bridge discovers compatible trainers on the local network or accepts a direct IP connection using the trainer’s network address.

It performs service discovery (finding the trainer’s available services), subscribes to telemetry (live trainer readings), and waits for the trainer’s control acknowledgement (confirmation) before enabling control commands.

## Progression and the garage 

The game layer borrows the 1–99 skill structure of RuneScape. Strength, Endurance, Agility, and Climbing gain experience from different aspects of a ride, including power, time, cadence, and simulated gradient (slope).

### Equipment and saved progress 

Earned Drops, the game’s currency, fund equipment in the garage, including frames, wheels, jerseys, and headwear.

Workshop upgrades, bounties (ride objectives), segments (sections of a route), and temporary bonuses give sessions additional objectives. These levels describe progress inside the game.

Progress is saved in the browser so the rider can return to the same character and equipment.

## Ride history and analytics 

The Stats panel brings together a power-duration curve (power sustained over different lengths of time), time in power zones (effort ranges), and ride history.

Session summaries include duration, distance, average and peak power, and accumulated energy. The power-duration view compares efforts from five seconds through twenty minutes when enough data is available.

### Storage and estimates 

The app keeps up to 50 archived rides in local browser storage and maintains lifetime totals. Virtual speed, calories, and FTP-related calculations (based on functional threshold power, an estimate of sustained cycling power) are estimates. Storage is local to that browser, with no automatic cloud backup.

## Trying the simulator 

Open the demo and select **Sim** to generate a ride. Choose Recovery, Endurance, Intervals, Sprint, or Climb to change its pattern. The same data feeds the dashboard, 3D scene, skill progression, and stats panels.

Use **Garage & Skills** to inspect progression and **Stats** to review the session. Keyboard shortcuts include **W/S** for shifting, **C** for camera views, and **L** for lighting. Select **Sim** again to stop.

The screenshots on this page come from that simulator. They show synthetic telemetry, rather than recorded personal workout results.

## Architecture and current state 

### How the pieces connect 

React and TypeScript handle the interface, Three.js renders the riding world, and shared modules define gearing and telemetry.

A Node.js service handles trainer discovery and the Direct Connect protocol (the trainer’s network communication rules), then relays state to the browser over WebSocket, a connection that lets the service and browser exchange updates.

### What runs in the public demo 

The public Cloudflare Pages deployment hosts the frontend (the browser interface) and simulator. Controlling a physical trainer requires the local bridge on the trainer’s network. The current release is an interactive prototype, with the simulator available for anyone to explore.

Related projects include my [COLMI smart-ring firmware for Zwift](<https://devanmetz.com/portfolio/colmi-r12-zwift/>) and [DIY electric bike](<https://devanmetz.com/portfolio/diy-electric-bike/>), which explore other sides of cycling hardware and telemetry.

## Build photos

![The Performance and Stat Review panel showing energy, ride duration, peak power, and a power-duration chart.](<https://devanmetz.com/_astro/kickr-stats.CqL7K2dG_FJnRX.webp>)

The ride review presents energy and power-duration data from a short simulated session.

![The Rider Guild and Garage with Strength, Endurance, Agility, and Climbing skill cards.](<https://devanmetz.com/_astro/kickr-garage.DEtZ3cY3_Z1UqbzY.webp>)

Game progression earned during the simulator session, with tabs for equipment, upgrades, quests, and segments.

## Build stories

- [One simulated ride, the whole cycling cockpit](<https://devanmetz.com/blog/kickr-core-hub-simulator/index.md>)

## Related reading

- [Market Atlas](<https://devanmetz.com/portfolio/market-atlas/index.md>)
- [Agent Message Board](<https://devanmetz.com/portfolio/agent-message-board/index.md>)
- [Goop Troops](<https://devanmetz.com/portfolio/goop-troops/index.md>)
