When I first sketched out the "Match Fitness" feature for Atmos Football, I genuinely thought it would be a weekend project.

The idea was simple: after recording a 5-a-side game, a player taps "Sync from Watch" and sees their distance, calories, and average heart rate attached to that match. One screen, three numbers, a sync button. How hard could it be?

The naive developer in me imagined installing a Capacitor plugin, pulling some data, and saving it to Firestore.

Seven phases, 29 distinct tasks, multiple Play Store submissions, a full privacy notice rewrite, and several late nights later — the feature finally shipped.

This is the story of how a "simple" fitness tracking addition became one of the most complex features I've built for Atmos Football, and what other indie developers should know before adding health data to their apps.

1. The Feature That Sounded Like a Weekend Project

The user story was genuinely compelling: give players a personal post-match summary of their physical effort. Distance covered, average heart rate, calories burned — all tied to a specific game.

What I didn't anticipate was that health data sits in an entirely different regulatory and architectural category from game scores. What began as a nice-to-have exploded into a project touching Firestore security rules, GDPR Article 9 compliance, Play Store Health Apps declarations, a custom workout-matching algorithm, and the account deletion flow.

2. Challenge #1: Health Data Is Not Normal Data

Under GDPR, not all personal data is equal. Player names and game scores fall under standard personal data, usually processed on a "legitimate interest" basis. Heart rate, GPS routes, and other biometrics are Special Category Data under Article 9 — the highest protection tier.

This single classification changed everything:

  • Explicit consent is required, separate from all other consents, off by default, and easy to withdraw at any time.
  • The privacy notice must specifically name each type of health data collected and state its lawful basis.
  • Users must be able to delete all their health data independently of their account.

For a feature only the individual player ever sees — never shared with the group — this felt disproportionate. Then I realised the regulation doesn't care who views the data. It cares that I, as the data controller, am processing sensitive biometric information.

The privacy notice went from a standard "we collect names and emails" document to a multi-section disclosure with lawful basis tables, third-party data source declarations (Health Connect), and retention policies specific to fitness data.

3. Challenge #2: The Play Store Gauntlet

Declaring Health Connect usage in Google Play Console triggers a serious review cascade.

You must complete the Health Apps declaration, then list every data type in the Data Safety section — Heart Rate, Distance, Speed, Calories — each with a collection purpose, encryption status, and whether it's required or optional. On top of that, Google requires a written rationale (~500 characters) explaining why your app needs health data. A human reviews it.

Then there's what I came to think of as the "Prove You're Not a Data Thief" video. Google may ask for a screen recording of you using the feature while narrating what each screen does. I spent an afternoon recording myself on an emulator, talking to an unknown reviewer on the other side of the world, trying to explain that my hobby football app wasn't secretly harvesting biometric data. Whether the video was actually watched, I'll never know. But the requirement looms over every submission until you're approved.

The privacy policy URL in the Play Console must also contain the keywords "Heart Rate", "Health Connect", and "Fitness" — Google's automated systems verify this at submission time.

All of this must be in place before the first build containing the health plugin is submitted. There is no "add compliance later" path.

4. Challenge #3: Matching a Workout to a Game

Once compliance was sorted, the core technical problem remained: users wear their watch all day. Which workout was the football game?

Health Connect can return multiple workout sessions on game day — a morning gym session, a walk to the pitch, the match itself, and a walk home. For recent scheduled games we use the expected kick-off time and query a ±90-minute window. For historical games (hundreds of past matches with no recorded kick-off time), we can only scan from midnight to midnight and rely on a scoring algorithm to find the best match.

The scoring formula ranks candidates by how closely their duration matches the expected game length:

score = 1 − |workoutDuration − expectedDuration| / expectedDuration

A score above 0.7 earns a "Best match" badge. Here's a typical Thursday evening, kick-off 19:00, expected duration 65 minutes:

Workout Start Duration Score Result
Morning gym 07:15 45 min Not shown — outside ±90 min window
Walk to pitch 18:40 18 min 0.72 Shown, no badge — too short
Football match 18:58 62 min 0.95 ✓ Best match
Walk home 20:05 15 min 0.77 Shown, no badge — too short

The app never auto-selects. The user always confirms. False positives — attaching gym data to a football game — would undermine trust in the feature permanently.

Edge cases are handled too: no workout recorded (offer manual entry), watch died mid-game (partial data is still useful), two workouts in the window with similar scores (show both, let the user pick).

5. Challenge #4: Data Isolation and the Right to be Forgotten

Normal app data is social and lives under groups/{groupId}/.... Health data cannot go there — it must be completely invisible to other group members, organisers, and admins.

The solution is a parallel private data tree: users/{uid}/fitData/{gameId}, with Firestore security rules that allow read and write only to the owning user. A linkedPlayers map on the group document (playerName → uid) bridges the two trees without exposing any private data.

The UI cleanly reflects this separation: game history is visible to everyone, but fitness columns and sync buttons only render for the linked player viewing their own data.

The GDPR "Right to be Forgotten" created one more trap. Deleting a Firebase Auth account does not delete Firestore subcollections. Deleting users/{uid} leaves users/{uid}/fitData/* as orphaned documents — still billable, still containing biometric data of a user who explicitly asked to be erased. The account deletion flow must explicitly load every document in the fitData subcollection and delete them individually before removing the parent. This is easy to forget and impossible to catch without specifically creating a user, syncing fitness data, deleting the account, and then checking Firestore directly to confirm the subcollection is gone. We added it to the smoke test checklist for exactly this reason.

6. Current Limitations: Android Only — For Now

The feature is currently Android-only via Health Connect. The web PWA only supports manual entry. The architecture was deliberately built to be platform-agnostic — the Firestore schema, security rules, and analytics UI work identically regardless of whether data came from Health Connect, HealthKit, or manual entry. Adding iOS would require only the HealthKit permission flow; everything else is already in place.

The manual entry form is also genuinely useful for historical games where a player remembers their stats but no longer has the watch recording.

Was It Worth It?

Right now this feature is used by exactly one person: me.

And yet I don't regret the effort. The real value was in the design decisions, not the code — the consent model, the data isolation architecture, the workout-matching approach, and the Play Store compliance checklist are all production-ready. If the app grows to hundreds of players tomorrow, the feature scales immediately: no data migration, no privacy notice changes, no architectural rework.

For other indie developers thinking about adding health features: expect to spend 80% of your time on compliance, architecture, and privacy design — and only 20% on the actual code.

The gap between "wouldn't it be cool" and "this is actually shippable" is enormous. But getting it right feels surprisingly good.

You can try manual fitness entry in the Launch Demo. Full watch sync is available on the Android version. For the longer journey of the app, see How We Built Atmos Football.

— James