Repository navigation
Releases: beadon/RacePlex
Release list
v0.7.1
Session sharing is available from the file browser, for any session on your device.
Share any session, not just a fresh recording
Every session row in the file browser (Garage → Files) carries a Share icon alongside Download and Delete. It opens the OS share sheet with the file attached and a message pointing the recipient at RacePlex to import and view it — the same mechanism v0.7.0 added to the phone-GPS recorder's "session saved" screen, now reachable from anywhere a session is browsed.
204 test files · 2,703 tests · GPL-3.0-or-later · runs entirely in your browser, with no account and no upload.
v0.7.0
Board presets prefill new vehicles with real specs, and a phone-GPS ride can be viewed and shared the moment it ends.
Vehicles can be selected from a list of sample options
Adding a vehicle offers a "Board preset" picker alongside manual entry: four flagship e-skateboards (Lacroix Nazaré Supersport, Stooge V7 CST, Radium Mach One S, Evolve Diablo Carbon), each sourced from the vendor's own published specs with a checked date. Picking one prefills engine, drivetrain, battery, weight, and the eSkate tire/custom-field block — the built-in eSkate setup template does the same for a new setup. Every field stays editable afterward, and manual entry remains the default. A free-form notes field on any vehicle holds a preset's performance highlights and source link as plain facts, with no pricing or marketing copy.
View and share a phone-GPS session the moment it ends
Ending a phone-GPS recording used to leave only "New session" — no way to look at the ride you just recorded, or hand it to anyone else. The "session saved" screen now offers View session (loads it straight into the map and chart) and Share (the OS share sheet, pre-filled with a link to open the file in RacePlex on another device — a phone, a laptop, whatever the person on the other end has), alongside starting fresh.
A clearer way to see what's loaded, and back out of it
Opening a session swapped in a different tab bar with no indication of which session you were looking at, and a "Tools" tab (Stance Visualizer, Seat Position Visualizer, My Data) that has nothing to do with a loaded ride — those calculators are still one click away from the dashboard. The header now reads "RacePlex › <session name>", making it clear both what's open and that clicking the logo takes you back to the dashboard. The Tools tab is gone from the session view.
Everywhere else
- Cleaned up remaining references to the project's old fork name ("Dove's DataViewer") in the contributor guide and a few other corners — RacePlex throughout.
- Stopped tracking mergeability with the upstream project this fork started from; its existing code remains the documented foundation, but new work follows RacePlex's own conventions.
204 test files · 2,703 tests · GPL-3.0-or-later · runs entirely in your browser, with no account and no upload.
v0.6.0
A release about batteries, heart rate, and a Bluetooth bug that had been breaking every live connection since v0.5.0.
Fix first: live Bluetooth connections were broken
If you tried pairing a VESC, BMS, RaceBox, or Dragy after v0.5.0 and hit an immediate failure, this is why: every live connection called addEventListener on the wrong object, so a connect attempt threw right away. A second bug meant that even when a connection succeeded, disconnecting it could hang — the app moved on, but the phone's Bluetooth stack kept holding the link open in the background. Both are fixed, verified against real hardware: a fresh connect-then-disconnect cycle now completes in about a quarter of a second.
A BMS is now a live data source, alongside VESC
A JBD-family BMS (sold as Xiaoxiang, Smart BMS, or Little Elephant) can now connect over Bluetooth as a third concurrent device, merging pack voltage, current, SOC, per-cell voltages, and MOSFET/pack temperatures into the session in real time — the same "connect it alongside your GPS source" pattern v0.5.0 introduced for VESC.
Neither sidecar needs a RaceBox or Dragy anymore. Connect a VESC and/or BMS straight from the phone-GPS recorder, and their data is captured even before you start moving — a pack heating up on the charger or an ESC being bench-tested is exactly the kind of thing worth recording while parked. A session with sidecar data now shows small "VESC"/"BMS" chips wherever you browse your sessions, so you can tell at a glance which rides carry that extra telemetry without opening each one.
The first VESC or BMS you connect gets remembered on a Garage vehicle profile (a new one if you don't have one yet), so reconnecting narrows the Bluetooth picker instead of showing every nearby device again.
Live heart rate
A fourth Bluetooth source: any standard heart-rate monitor — a chest strap, a fitness watch, an Apple Watch running an active Workout session — connects the same way VESC and BMS do, using the open Bluetooth SIG Heart Rate Service rather than a reverse-engineered protocol. A heart-rate monitor belongs to you, so it's remembered as your own device preference rather than tied to a specific board the way VESC/BMS are.
Recording is now the front door
The bottom nav's primary action is now Record — a filled button that opens the same recording flow the dashboard's "Record a session" tile always has, without scrolling. Tools (the trackside calculators) moved out of that nav bar into Settings, a better fit for something used occasionally rather than every session. The Tools picker's "Lap Timer" entry is gone too — it was a second, confusing door into the exact phone-GPS recorder the dedicated Record flow already opens.
Session lists no longer dump everything at once
Both the dashboard's Recent Sessions list and the file browser's Track→Course view now page 10 sessions at a time with a "Show more" control, instead of a hard cap (dashboard) or an unbounded list (file browser). A session with a lot of extra telemetry channels — VESC and BMS together can add close to 20 — no longer pushes the map off-screen either: the chart legend now scrolls within a fixed height instead of growing without limit.
Everywhere else
- Cancelling the Bluetooth device picker now just returns you to the connect button, instead of showing an error with troubleshooting text that didn't apply.
- The README now carries a feature comparison against RaceChrono, the established commercial option — including two honest gaps: the track library is one built-in track today (growing through community pull requests), and there's no writer yet for NMEA/VBO/CSV/ODS session export.
202 test files · 2,685 tests · GPL-3.0-or-later · runs entirely in your browser, with no account and no upload.
v0.5.0
A release about riding with a VESC, riding without touching your phone, and trusting what the map shows you.
Record your VESC alongside your GPS
A VESC-based ESC can now connect over Bluetooth as a second device while you record with a RaceBox, a Dragy, or your phone — no post-ride CSV import needed. The two streams merge live, matched by receipt time; a pairing that goes stale (a dropped connection, a few seconds of lag) is flagged rather than silently presented as clean. If two apps try to hold the same VESC connection at once, the error now says so plainly instead of leaving you retrying a connection that can't succeed.
Tap the connected VESC's status to open a full gauge dashboard — current, power, duty, speed, battery, temps, consumption, odometer, trip, and up-time — modeled on VESC Tool's own RT Data screen, with tick-mark rings and needle pointers. Verified against real hardware, including a firmware old enough to warn about its own age.
Pick how you're recording
The record flow now asks up front: Simple logger (just record, sort it out later), Drag race logger (0-60, quarter mile, trap speed), or Track logger (circuit or point-to-point). Whichever you pick tags the session so later views can focus on the metrics that actually matter for that kind of run.
GPS gaps are now visible
Android stops delivering GPS updates once a recording tab loses the foreground or the screen sleeps — a limitation of running in a browser tab. Until now, a session that suffered this looked like a normal, if short, ride: the map drew a straight line across the gap and the chart interpolated a smooth curve, as if both had actually happened.
A gap between fixes now gets flagged: the map leaves a visible break in the line where the gap was, and the chart does the same, with a banner reading "GPS gap detected — Xm Ys of this session wasn't recorded."
The phone-GPS recorder also gained a lock screen: hold a ring to unlock, tap-proof against a phone jostling in a pocket. A web page can't override a deliberate power-button press, so the precision warning says so up front; the lock screen covers the far more common case of the screen simply timing out mid-ride.
Everywhere else
- This device got its own top-level tile next to external loggers — no digging through a device picker to record with just your phone's GPS.
- iOS Safari riders who deny location now get a direct explanation and a way back in.
- A PWA update that used to freeze on a white screen now completes cleanly.
- The build version shows on the home page itself.
Under the hood
Phone-GPS sessions now save as .rplx, an extension RacePlex owns. .dovep, the previous extension inherited from the project this app forked from, still opens exactly as before — nothing needs to be migrated.
194 test files · 2,621 tests · GPL-3.0-or-later · runs entirely in your browser, with no account and no upload.
v0.4.0 — Report a data issue, and live recordings that reopen
A release about the moment right after a ride: a file that won't display, and a session recorded live that wouldn't reopen.
On the numbering. RacePlex restarted versioning at
0.xwhen it forked from Dove's DataViewer. Thev2.x/v3.xtags in the git history belong to upstream and came along with their commits.
Report a data issue
Until now, "my file isn't displaying right" had nowhere to go but a description and a guess. RacePlex has no server, so Settings → Report a data issue (also in the Tools tab and the Files drawer) runs the file through the app's own parser on your machine and builds a diagnostic report: whether it parsed, how many rows were accepted or rejected and why, what channels were detected — never your raw coordinates. It hands you a prefilled GitHub issue to open yourself; that needs a free GitHub account, which the dialog says up front, and the issue is public, which it also says before you attach anything.
Live recordings can be reopened now
A RaceBox or Dragy session recorded live over Bluetooth displayed fine right after recording, saved to the file manager — and then failed to reopen, with no error shown. The save format was ad hoc JSON under a made-up extension the app's own parser had never heard of. Both now save as .rplive, one small versioned package with a real parser, named with what recorded it and when.
The Files drawer also stopped hiding failures generally: a file that fails to reopen or import now shows an error instead of doing nothing.
Under the hood
TypeScript 7, run side-by-side with the TypeScript 6 compiler API that typescript-eslint still needs — the official migration path, not a downgrade.
In progress
Drag-run analysis (0-60, 1/4 mile ET, trap speed) has a tested model behind it — every crossing interpolated, checked against the closed-form physics of a constant-acceleration run — but no UI yet. Not in this build.
Fixed
- The Files drawer swallowed reopen and upload parse errors silently; both now show a toast.
- The Files drawer's manual-upload picker was missing several supported extensions (
.dovex,.xrk/.xrz,.ibt,.mp4,.fit). - The track editor's Add/Edit Course dialog let the map render inside a fixed 384px box regardless of screen size; it now uses the full screen.
- The About dialog listed cloud sync and an AI coach — neither exists in a stock build — and omitted VESC, GoPro, FIT, RaceChrono, live capture, the stance tool, and data export, all of which do. It now also shows the build's version and links to the exact commit.
185 test files · 2,542 tests · GPL-3.0-or-later · runs entirely in your browser, with no account and no upload.
v0.3.0 — Live on the web, installable on your phone, and your data is yours
The release where RacePlex became something you can actually keep on your phone — and where your data became yours to take with you.
On the numbering. RacePlex restarted versioning at
0.xwhen it forked from Dove's DataViewer. Thev2.x/v3.xtags in the git history belong to upstream and came along with their commits.
It's live, and it installs
beadon.github.io/RacePlex — open it and it runs. Nothing to install, no account, no upload.
If you want it on your phone, add it to your home screen and it works like an app, offline, at the track with no signal. That needed HTTPS: a browser will only register a service worker on HTTPS or localhost, so over a plain-HTTP LAN address navigator.serviceWorker doesn't even exist and the offline copy could never be built. GitHub Pages serves over HTTPS, which is the whole requirement.
Serving from a subpath (/RacePlex/) quietly broke four things, all fixed here: runtime asset fetches (/tracks.json was resolving outside the deployment, so the track list came up empty with no visible error), the PWA manifest's start_url and scope, the router basename, and the self-hosted fonts, which 404'd on every deploy.
Your data is yours
Everything RacePlex knows lives in your browser and nowhere else. That is the point of it — no server sees your rides. It is also the risk: clear the browser, or move to a new phone, and it is all gone.
Settings → Your data now downloads the lot as a .zip:
- every session log, in its original format (so they open in other tools too — you are not locked in),
- your vehicles, setups, notes, custom tracks, lap snapshots and settings, as plain JSON you can read in any text editor,
- your saved CSV column mappings, so a device you taught RacePlex to read once stays readable.
The same screen restores an archive, which is how you move to a new browser or a new device. Restoring never overwrites a session that's already there. Session videos are included only if you tick the box, because they can run to gigabytes.
The export is also on the Tools tab and in the Files drawer, under the storage bar — the moment you see how full the browser is, is the moment you want a way out of it.
A home screen
The app now opens on a dashboard instead of a welcome page: your recent sessions first, then your garage, tracks, devices and tools, with a persistent nav bar across the top (or along the bottom, on a phone). Adding data is its own zone rather than the only thing on screen.
Compare sessions side by side: pick two or more from the browser and they're resampled onto a shared distance axis, so the same corner lines up across runs on one map.
Local users. More than one rider sharing a browser now gets their own sessions, garage and settings, without an account.
Recording and importing
RaceBox and Dragy record live over Bluetooth. No logger file to export first — connect and go. Chrome or Edge, desktop or Android.
FIT files import (Garmin, Wahoo, Coros, Suunto). This is the largest installed base of GPS fitness devices, so you can try RacePlex with a ride you already own. They log at about 1 Hz — roughly 11 m between fixes at 40 km/h — which is enough to plot a ride and too coarse to place a braking point.
RaceChrono CSV v3 imports.
GoPro chapter-split recordings fold into one session. A long recording is split across several .mp4 chunks; they now stitch into a single continuous timeline.
The stance tool now tells the truth
The old version compared your board's grip against the 0.37 g at which a board pitches over the nose, and told nearly every rider they'd tip before they'd skid.
That is true of an all-wheel board, and false of almost every board actually being ridden. An eskate has no friction brakes — the motors are the brakes — so only the wheels a motor drives can slow it down, and nearly every board is rear-driven. On a rear-driven board, braking unloads the very wheels doing the braking. As the rear lightens it loses the grip it needs to brake, so it can never reach the threshold that would lift it:
a_slip / a_endo = μ·f·z / (L + μ·f·z) < 1 for every board, always
A dual-rear board tops out around 0.17 g — under half of what an endo needs — and the rear breaks traction and slides instead. It cannot endo under motor braking, on any geometry. An all-wheel board keeps the full ~0.6 g of urethane grip and does pitch, with the rear lifting at around 0.37 g.
The tool now reports your g budget against what your drivetrain can actually deliver.
Under the hood
A major-version dependency migration: React 19, Tailwind 4, Vite 8, TypeScript 6, ESLint 10, react-router 7, react-resizable-panels 4.
That last one is worth calling out, because it shipped a bug with a fully green build. react-resizable-panels v4 silently redefined a bare size number from percent to pixels (a unitless string is now percent). The prop is typed number | string, so defaultSize={30} still compiled — and the Pro view's left column rendered as a 30-pixel sliver with its labels wrapping one letter per line. tsc, ESLint, ~2,500 tests and the build were all green. Only opening the app found it.
Fixed
- The Pro view's left column rendered as a ~45px sliver after the resizable-panels bump.
- Self-hosted fonts 404'd on every deploy.
- The track list silently came up empty on the deployed site.
- The locale parity check passed while broken, because a test's exit code was being masked by a pipe.
v0.2.0 — eskate telemetry works
The first release in which RacePlex works for electric skateboards.
On the numbering. RacePlex restarted versioning at
0.xwhen it forked from Dove's DataViewer. Thev2.xtags in the git history belong to upstream and came along with their commits. This tag is RacePlex's baseline; the next release will bev0.3.0.
Eskate telemetry
Until this release, no eskate app produced a file RacePlex could open. VESC Tool, FreeSK8, Metr, Float Control and the official Onewheel app all log GPS in their own layouts, and all of them were rejected.
VESC Tool import
A VESC ride log now imports, and the ESC channels come with it. Motor current, battery sag, duty cycle, ERPM and temperatures are charted on the same timeline as the GPS trace. A nosedive appears as a duty-cycle spike, which a GPS trace can only show you after the fact.
A VESC log writes ESC data at about 12 Hz and GPS fixes at about 1 Hz. RacePlex keeps every ESC row at full rate and interpolates position between GPS fixes, so a 0.2-second duty-cycle spike is still visible.
Generic CSV import
Most delimited logs containing a latitude and a longitude will now import: Float Control, pOnewheel, Metr, TrackAddict, Qstarz, or a logger we haven't seen.
RacePlex detects the delimiter, maps the columns by name, and shows you the mapping so you can correct it before importing. Your correction is saved against that device's column layout, so you're only asked once.
The column mapper exists because these formats have unstable column sets. pOnewheel, for instance, generates its columns per ride from whichever BLE attributes it recorded.
GoPro .mp4 import
GoPro stores GPS inside the video file. Drop the .mp4 in and RacePlex reads the telemetry track in the browser, with no conversion step and nothing uploaded. It adds 0.58 kB to the main bundle; the 235 kB decoder loads only when you import a video.
The HERO12 has no GPS. GoPro removed it for that model.
Lap timing
Point-to-point courses
A hill run, slalom or drag pass finishes somewhere other than where it started. Lap timers that model only a circuit find no laps in such a session. RacePlex handles both.
Lap timing with no setup
When a datalog records where its timing lines were, RacePlex reads them back and times the run:
- from a GPX file's
StartandFinishwaypoints, or - by reconstructing the timing lines from RaceBox's lap-number column, which records when the device crossed a line while the GPS columns record where you were.
Checked against the device: RaceBox reports a run of 36.480 s. RacePlex computes 36.547 s from the GPX and 36.520 s from the CSV. The 67 ms difference comes from interpolating the line crossing rather than quantising it to a sample.
Stance tool
Foot position, weight distribution, and the braking deceleration at which the rear wheels unload.
A board reaches that point at around 0.37 g, below the roughly 0.6 g that urethane can grip, which is why boards nosedive under hard braking. The same calculation for a kart gives about 2.1 g.
Sliders control foot positions, weight split and crouch. A stick figure tracks the sliders, and a plumb line from the centre of gravity shows where your weight falls between the trucks. Rider centre-of-mass height uses the standard anthropometric figure of 0.55 × stature (Winter, Biomechanics and Motor Control).
Other formats
GPX and RaceBox CSV, with automatic speed-unit detection. RaceBox writes its Speed column with no unit in the header, and it isn't in m/s, so RacePlex measures the column against speed derived from the positions.
Identity
- eSkateboard is the default vehicle type: deck, trucks, wheels, drive, battery, rider weight. Kart is still available.
- New brand: Racing Red
#BD162C, Carbon Black and Electric Yellow. Five colour palettes, all checked for WCAG AA contrast. - A Supported Devices list with sample rates, prices and the format to export. It's plain data (
src/data/supported-devices.json); to add a device, open a pull request. - Removed: the sponsor button, the feature roadmap, the cloud-storage incentive, Terms of Service, the "Operated by" footer, and the proprietary AI-coach plugin. RacePlex asks for nothing and sells nothing.
Format details that are easy to get wrong
- RaceBox's CSV
Speedcolumn has no unit, and it isn't m/s. Assuming a default makes every speed 3.6× wrong, and the charts still look reasonable. - VBO stores coordinates in minutes, with longitude positive-west. A file read with the wrong convention still plots, in the wrong hemisphere at 1/60th scale.
- VESC logs have no
kmh_gnsscolumn, despite the name appearing in many places. The speed column isgnss_gVel, in m/s. - Dragy has no CSV export. The vendor confirms this.
These are documented with sources in docs/research/FORMATS.md.
Known gaps
Tracked in the open issues:
- No live capture. You can import a RaceBox or Dragy file, but not record from one over Bluetooth (#32).
- GoPro chapter-split recordings import as separate sessions (#29).
- FreeSK8 and Metr: the schemas are confirmed, but we won't ship a parser we can't test against a real file (#34).
- Non-English translations are best-effort; English is the source.
If you own hardware we haven't tested, sending a sample export file is the most useful thing you can contribute. Every format detail above came from opening a real file.
166 test files · 2,360 tests · GPL-3.0-or-later · runs entirely in your browser, with no account and no upload.