Valen: Recovery Modelling & ML Sandbox valenapp.tech ↗
Valen is a fitness app I built solo and shipped to production. It models how fatigued each muscle group is and turns that into a daily training decision. It's also my sandbox for applied data science: I use its own data to test whether the model is actually right.
Architecture
A cross-platform React Native client with a local-first data layer: every session is written on-device first, so logging works offline and never waits on a network call. Firebase handles auth, cloud backup and restore of training history, and subscription entitlements across iOS and Android. The recovery engine is plain deterministic JavaScript in the client, which keeps it fast, testable and explainable.
The recovery model
Each muscle zone carries a fatigue score from 0 (fresh) to 100. A session bumps the score for the zones it trained, then the score decays exponentially with time, at a per-zone rate:
Larger muscle groups decay more slowly, so legs stay fatigued longest. The homepage renders these scores as a body heat map, so readiness is visible at a glance instead of buried in tables. Early on there's no history to calibrate against, so the engine starts from conservative defaults and a compressed four-step onboarding.
Experiment 1: does the formula match how workouts felt?
For each logged session I computed what the model predicts the remaining fatigue to be, then compared it with the perceived exertion the user reported (easy, good, wiped). Data: a 62-session sample backup, 59 usable after cleaning. It is sample data, not real user data.
The numbers run the wrong way: sessions people called "easy" scored higher predicted fatigue than "wiped" ones. Scaling the starting spike by session intensity, instead of a flat 100, improved the shape but didn't fix it. The honest reading is that the sample is small and the real driver, how someone feels that day (sleep, mood, energy), isn't logged by the app at all. Result: the formula stays, and the next feature is capturing that missing signal.
Experiment 2: exercise to muscle-zone classifier
Valen ships with 202 hand-tagged exercises. Can a model learn the tagging well enough to suggest a muscle zone when a user adds a custom exercise? I dropped the 21 cardio entries (an activity, not a muscle), leaving 181, one-hot encoded movement pattern and equipment, and used a stratified split: 135 for training, 46 the model never sees.
Movement pattern (pull, isolation, push) and bodyweight-vs-equipment carried most of the signal in the feature importances. Caveat: most exercises train several zones, so this is really a multi-label problem, and predicting only the primary zone is a deliberate simplification. Next step is multi-label output and a better model than a single tree.
Shipping it, not just modelling it
The ML experiments are the part I enjoy writing up, but most of what I learned came from having to put the thing in front of real people. Owning it end to end meant learning the unglamorous half of software: a build and release pipeline that gets a signed binary onto two app stores, testing that catches a regression before a user does, crash and analytics instrumentation, and the slow work of fixing what the data says is broken.
It also let me take design seriously for the first time. I designed every screen myself, and the fatigue heat map went through several versions before it read clearly at a glance. Getting to make those calls, and then watch real users respond to them, turned design from something I appreciated into something I practise.
Engineering notes
- Subscription entitlement handling across iOS and Android edge cases was the hardest engineering problem, harder than the recovery maths.
- Two logging modes: a three-step Quick Log for mid-session use and full logging when precision matters, to keep data quality up without adding friction.
- Users trusted the readiness score more when the app showed why it said what it said. Explainability was a product feature, not just a nicety.
Live in production at valenapp.tech.
Featured in Android Planet's Best Apps of the Week issue.