Blog
Technical notes, training science, and product updates from the pacelore team.
Six months of pacelore
What we shipped, what we learned, and where the project stands.
Backfilling a Strava history through the API
Rate limits, deduplication, and making a long import safe to re-run.
Building a workout library for Garmin and Zwift
60 structured sessions, FIT export, .zwo export, and the step schema behind them.
Why PolyForm Noncommercial over MIT
The license choice that lets anyone self-host pacelore but blocks commercial wrappers.
Segment matching with Dynamic Time Warping
How pacelore finds your effort on a segment even when GPS lines don't overlap perfectly.
Peak power curves: the mean-maximal power chart
What the MMP curve shows, how it's computed, and why it's paywalled everywhere else.
Deduplicating activities across Garmin, Zwift, and Strava
The same ride can arrive from three sources. Here's how we keep exactly one copy.
ATProto and athletic data portability
Why we wired optional Bluesky export into the ingest pipeline.
Arweave permanence: your activities should outlive any startup
One-time write to a permaweb means your FIT files survive if pacelore disappears.
Running pacelore: $0.012 per athlete per month
A line-by-line breakdown of the Cloudflare bill and how the math works at scale.
TSS three ways: power, heart rate, pace
Power TSS, hrTSS, and rTSS — the same idea computed three different ways.
Grade-Adjusted Pace and the Minetti model
How to flatten a hilly run into a comparable flat effort using metabolic cost equations.
Normalized Power in 20 lines of TypeScript
The 4th-power moving average that makes sense of variable-effort rides.
FIT, TCX, GPX: a field guide to fitness file formats
What each format contains, where it comes from, and how we parse all three.
Why we chose Cloudflare D1 over Postgres
The tradeoffs of a SQLite-at-the-edge database for a multi-tenant fitness platform.