A multi-role mobile product: wearable health data, injury-risk scoring, and paywalled reports — with Stripe entitlements and layered client/API security.
I built the Flutter app, marketing site, and admin end-to-end. I owned the NestJS API with other engineers on the backend.
What an athlete opens every day: this week's load, sleep, and the next session.
Injury-risk dashboard
Injury-risk dashboard
Wearable data turned into who is overreaching. Coaches see this; players only see it if their package includes health.
Decisions
One Flutter app with role-correct shells (player, coach, club, league, scientist) instead of five client codebases.
NestJS as the source of truth for billing and health so the app never invents a paid or scored state.
Encrypt sensitive payloads on the device and pin TLS — health and payments are treated as adversarial, not as a launch checklist.
What I built
Shipped the Flutter app (Riverpod, Retrofit, flavor-aware builds, localization) with a distinct home shell per role.
Built the marketing site (join funnel, i18n, SEO) and the internal admin (leads, billing ops) as the only client author.
Stripe subscriptions and club packages with a pending→active state machine — no false “subscribed” before payment. Entitlements refresh on resume so package changes take effect immediately.
Health pipeline: wearable sync → biomarkers and injury-risk series → Pulse dashboards, paywalled when packaging excludes health. Empty-data UX stays honest when wearables have not filled scores yet.
Client security: hybrid RSA+AES payload encryption before the request leaves the device, TLS pinning (fail-closed), runtime instrumentation / root / proxy checks. API: device-binding, stolen-refresh invalidation, encrypted auth routes.
Docker Compose + nginx promotion path so flavors and env actually match what users hit.
Outcome
In production on device builds, with a private walkthrough on request.