GPX Editor (CycleEdit)
A browser app that reads cycling activities from GPX and FIT files, shows their metrics on a chart and a map, and shifts the power data to a new average, without uploading the file anywhere.
- Role
- Author
- When
- March 2026 to June 2026
- Stack
- JavaScript, Chart.js, Leaflet, Garmin FIT SDK
Context
Bike computers and apps such as Garmin Connect and Strava export rides as GPX (an XML list of track points) or FIT (Garmin's binary format). Sometimes you want to correct the data afterwards, for example when a power meter read consistently high or low on one ride. Most tools for that upload the file to a server. I wanted something that runs in a browser tab and keeps the file on your machine.
What I built
The app, published as CycleEdit, is a static site written in plain JavaScript modules:
- Load one or more
.gpxor.fitfiles. GPX is parsed with the browser's XML parser, including the Garmin track point extensions for heart rate, cadence and power. FIT is decoded with Garmin's official FIT SDK, which is loaded from a CDN only when a FIT file is opened. - Review the ride: distance, duration, elevation gain and loss, average and maximum speed, average power and normalized power, and a per lap table when the file contains laps. A Chart.js chart switches between elevation, power, heart rate, cadence and speed, and a Leaflet map draws the track.
- Edit power with a slider for the target average. Every power sample is shifted by the same number of watts (the difference between the target and the original average), so the effort keeps its shape. An earlier version multiplied the values by a ratio; the current one uses this additive shift.
- Export the edited ride as GPX, with power, heart rate, cadence and speed written back into the standard extensions. FIT files are exported as GPX.
A small test suite covers the parsers, the utility functions (distance, elevation, normalized power) and XML namespace handling, and a service worker caches the app's own files so it loads quickly on later visits.
Privacy
Files are read with the FileReader API and processed in memory. There is no backend and no upload step: the only network requests are for the app itself and its libraries (Chart.js, Leaflet and, for FIT files, the FIT SDK).
Status
The interface is in Italian. Its upload screen still mentions editing speed, which the current version does not offer: only power can be changed.