Case study
TrackerMax
A workout tracker with a real watch app on both platforms.
- Role
- Builder and owner
- When
- 2024 to present
The problem
What made this hard
Logging sets on a phone mid-workout is friction: wet hands, a locked screen, a lost rest timer. Most Flutter trackers treat the watch as an afterthought because Flutter does not run there. I wanted the phone to stay in the bag while the wrist does the logging.
What shipped
Built, wired, released
Native watch apps, not webviews. A SwiftUI app on watchOS and a Jetpack Compose module on Wear OS talk to the Flutter phone app through one Dart API over watch_connectivity. Complete sets, add sets, adjust or skip rest, all from the wrist.
Apple Health and Health Connect, wired both ways. Finished workouts are written out, and heart-rate plus active-calorie series recorded by the watch are read back into a vitals card. External workouts are deliberately never imported, so nobody farms the leaderboard from another app.
A server-scored leaderboard. Points are computed in a Cloud Function when a workout lands, with caps per set, per PR and per session length, so the weekly board rewards consistency instead of spam.
Weekly streaks with a grace window. One missed week per eight is forgiven, and the rules are mirrored in Dart and TypeScript with standalone tests on both sides.
The workout follows you off the app. Live Activities on the lock screen and Dynamic Island during sessions, plus home-screen widgets through WidgetKit on iOS and Glance on Android.
The unglamorous rest, done properly. RevenueCat subscriptions with the paywall UI, Hive-backed offline writes, and progress charts down to per-exercise history.

Architecture
How it holds together
L0One Flutter app owns state through GetX controllers; a watch sync service builds a flat diff-gated payload, so the radio link stays quiet between changes.
L1Watch actions are string constants declared identically in Dart, Swift and Kotlin, which keeps three codebases honest with each other.
L2Firestore plus TypeScript Cloud Functions for leaderboard scoring, notifications and routine data; scoring runs server-side so the client is never trusted with points.
L3Streak logic is a pure module tested in isolation, then mirrored to the backend.
Leaderboard points per workout, by source: Base 50 points (every qualifying workout); Sets 80 points (2 per set, up to 40 sets); Duration 60 points (10 per 15 min, up to 90 min); PRs 75 points (25 per PR, up to 3). Total 265.
On top of that, weekly bonuses: 100 for hitting the week's target, 200 at a 4-week streak, 500 at 12 weeks. A workout under 10 minutes, or under 3 sets, scores nothing.
Screens
From the actual build
Every frame is a real capture unless labeled otherwise. Tap any screen to open it.
Outcome
Where it landed
- Live on the App Store with the watchOS companion.
- Wear OS module shares the phone app's application id, as the Wearable Data Layer requires.
- Anti-abuse scoring and streak rules run server-side, mirrored and tested in two languages.

