Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

109 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Walk the World

A live progress tracker for two journeys at once. Log the distance you walk and the height you climb, then watch yourself walk along a long-distance trail while a second bar carries you up a famous mountain. Every walk counts twice, its horizontal distance against a route and its vertical ascent against a summit, on a full-screen map with running stats, records, a daily streak, and a finish-line celebration.

Pick from 15 trails (the Appalachian Trail, the Pacific Crest Trail, Te Araroa, the Tour du Mont Blanc, and more) and 15 mountains (Everest down to Toubkal). The route and mountain you choose are stored server-side, so the browser and the treadmill agent always agree on what your next walk counts toward.

Walks can be logged by hand or captured automatically from a treadmill with a small background agent that connects over Bluetooth and posts each walk for you, distance and ascent together. Either way, the map updates live, with no refresh.

The tracker ships as a single Rust binary that serves the JSON API and embeds the built React UI. Run it, then open it in your browser.

Technology stack

  • Backend: Rust, axum, SQLite (via sqlx), Server-Sent Events for live updates.
  • Frontend: React + TypeScript + Vite, MapLibre GL via react-map-gl, TanStack Query, Tailwind, Turf for progress-along-the-line math.
  • Treadmill agent: Rust, btleplug for Bluetooth, reqwest for posting walks. Speaks standard FTMS.
  • Shared types: Rust structs are the single source of truth. ts-rs generates the matching TypeScript definitions.

Project layout

crates/
  api-types/         Shared DTOs (source of the generated TS bindings)
  storage/           SQLite persistence for walks and the current selection
  server/            axum HTTP server that embeds the built UI
  treadmill-agent/   Background agent that logs walks from a treadmill over Bluetooth
web/                 React + Vite frontend
scripts/             One-time route geometry generator
setup.ps1            Registers the server + agent as Windows scheduled tasks

Running it

Development (hot reload)

Two terminals:

# 1) API server on :8849
cargo run -p server

# 2) Vite dev server on :5173 (proxies /api to :8849)
cd web && pnpm install && pnpm dev

Then browse http://localhost:5173.

Production (single binary)

Build the UI, then run the release server, which serves everything on :8849:

cd web && pnpm build
cargo run --release -p server

Then browse http://localhost:8849. In release builds the UI is baked into the binary. In debug builds the server reads web/dist from disk at runtime, so a UI rebuild shows up on refresh without a recompile.

How progress works

Every walk stores a horizontal distance and a vertical ascent in meters. Distance accumulates against the selected route, ascent against the selected mountain, and the two totals drive the two progress bars independently. Routes and mountains live in web/public/data, each keyed by a stable id that the walk log references. The map draws the selected route from its GeoJSON line and places the marker at the fraction of the trail you have covered.

The database is seeded with a default route and mountain on first run, so there is no unset state to handle. Distances are stored as canonical integer meters and everything else (kilometers, percentages) is derived for display.

Automatic treadmill capture

The treadmill-agent binary logs walks from an FTMS treadmill with no manual entry. A treadmill only advertises over Bluetooth while it is powered on, so one power-on window is one connection. The agent scans, connects when the treadmill appears, follows its cumulative distance and instantaneous inclination, and logs each walk. Ascent is the inclination integrated over the distance covered. Pausing the belt keeps the walk open, and resetting the console or powering off closes it out.

Run it alongside the server, on a machine with Bluetooth in range of the treadmill:

cargo run -p treadmill-agent

By default it matches treadmills whose Bluetooth name starts with FS- (a FitShow module). Override the prefix for a different machine:

TREADMILL_NAME=MyTreadmill cargo run -p treadmill-agent

It posts to the same POST /api/walks endpoint the web form uses, leaving route and mountain unset so the server stamps each walk with the stored selection. Captured walks show up in the history and on the map immediately. If the server is not reachable, a walk is skipped and logged, and the manual form stays available as a fallback.

Running both at logon (Windows)

setup.ps1 registers the release binaries as scheduled tasks so the server and agent start at logon (the agent one minute later, so Bluetooth is ready). Build the binaries first, then run the script once from an admin PowerShell:

cargo build --release
.\setup.ps1

API

Method Path Description
GET /api/progress Global totals plus per-route and per-mountain sums.
POST /api/walks Log a walk (distance + ascent) and return the stored row.
GET /api/walks List all logged walks (newest first).
DELETE /api/walks/{id} Delete a single walk by id.
GET /api/selection The current route + mountain selection.
PUT /api/selection Replace the current selection.
GET /api/events Server-Sent Events stream that pings on every change.

A logged walk may omit route_id and mountain_id, in which case the server fills them from the stored selection. This is what lets the treadmill agent post without knowing what you have selected.

Regenerating TypeScript types

After changing any #[derive(TS)] type in api-types, regenerate the bindings in web/src/types/:

cargo test -p api-types

Regenerating route geometry

The trail lines in web/public/data/routes/ are pre-generated from OpenStreetMap. To rebuild or add one, edit the relation ids in the script and run it. Existing files are skipped, so a flaky Overpass run can just be repeated:

node scripts/build-route-geometry.mjs

About

A single Rust binary that tracks your treadmill walks as live progress along the world's great long-distance trails and up its famous mountains.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages