Table of Contents
07 — Activity tracking
Technical reference. For task-based help, see the corresponding user guide.
Documentation status: complete for the current implementation
Reviewed: 2026-07-21
Primary users: family members and assigned coaches with activity permissions
Surfaces: mobile web app and platform API
Purpose
Activity Tracking records a baby's day-to-day care in seven consistent trackers. Each tracker combines fast entry, a full manual form, baby-scoped history, correction/deletion and timezone-aware grouping. Tracking remains available when premium analysis access is inactive.
Entry points
Family tracking routes use /family/track/:activityType. Coach view-as uses /coach/families/:familyId/track/:activityType and carries an explicit babyId. Home cards, reminder notifications, floating timers and Analysis chart points can all open the same tracking/edit surface.
Supported activity types are breastfeed, bottle, sleep, nappy, pumping, medication and solids.
Shared tracking workflow
- Confirm or switch the baby at the top of the tracker.
- Use a tracker-specific quick action, choose timer/manual entry where offered, or open the full form.
- Review the generated date/time and details, add an optional family note, then save.
- The newly saved item appears in date-grouped history and updates Home/Analysis through refresh and realtime events.
- Select a history row to correct it or delete it when the current actor has write permission.
Family notes belong to the family-authored record. A coach can read them as permitted but the coach edit flow does not overwrite them; coach-only context is stored through the separate private-note feature.
Tracker fields and rules
| Tracker | Captured details | Important validation / quick entry |
|---|---|---|
| Breastfeeding | Date, start, end, left/right side and note | Left and Right start a timer; manual ranges require valid start/end values. |
| Bottles | Date/time, positive amount, ml/oz, breast milk/formula and note | Quick choices prefill common milk/type combinations; amount must be greater than zero. |
| Sleep | Date, start, end, day/night, mood, environment, settling time and note | Timer or manual entry. Mood: content/restless/unsettled/wired. Environment: co-sleeping/contact napping/baby cot/motion nap/other. Settling bands are <10, 10–20, 20–30, 30–40 or >60 minutes. |
| Nappies | Date/time, wet/dirty flags, optional image and note | Wet, Dirty and Mixed are quick saves. At least one of wet/dirty is required. Images use authorized signed storage. |
| Pumping | Date, start, end, side, positive amount, ml/oz and note | Left and Right can start timers; amount must be greater than zero. |
| Medication | Date/time, medication name and note | Medication name is required after trimming whitespace. |
| Solids | Date/time, meal note, allergic reaction, accidental exposure, optional ladder/stage | A reported reaction or accidental exposure reveals and requires the matching explanatory note. Ladder/stage links must belong to the same baby. |
For Breastfeeding, Sleep and Pumping, the full form rejects invalid ranges and start/end values more than two minutes in the future. Sleep overlap or implausible-gap findings are presented as explicit warnings to review/confirm rather than silently rewriting the user's times.
History and navigation
- History is filtered to the selected baby and current tracker, sorted newest first and grouped by the family's local date.
- The space between records is labelled; Sleep uses awake-gap language.
- Cursor pagination loads older records without replacing the current page.
- Solids can be filtered to Reactions only.
- Range activities show duration and start/end details; point activities show the recorded local time.
- Sleep entries that cross midnight follow the product's sleep-day attribution so Home, history and Analysis agree.
- Changing the selected baby resets the tracker query and prevents records from the previous baby appearing under the new heading.
Save, edit and delete behavior
New records send a UUID clientMutationId. The platform derives occurredAt from the relevant start/time, stores the supplied IANA timezone and a local-date key, and treats mutation retries idempotently. Timer saves also include activeTimerId so completing a stopped timer and creating its activity form one durable operation.
If a realtime refresh indicates that the open activity changed elsewhere, the editor blocks an overwrite and asks the user to reload or close the stale edit. Deletion requires an explicit user action and removes that activity from subsequent Home, history and Analysis views.
Only creates have a persistent offline outbox. An offline create appears as pending/failed and can retry or be discarded. Existing-record edits and deletes require the server and must not be presented as durably queued. Timer review and offline mechanics are detailed in Feature 08.
Coach actor / family subject behavior
- The coach route resolves the selected family and baby as the data subject while retaining the coach as actor.
- A current assignment with
canWriteActivitiespermits activity create, edit and delete; read-only assignments cannot mutate. - Coach-created/edited records are audited by the platform.
- Coach writes omit the family note field, preserving any existing family-authored note.
- Revocation or expiry is checked again on every API operation; hiding buttons is not the security boundary.
Loading, error and conflict states
| State | Expected behavior |
|---|---|
| No baby | Direct family self-mode to add/select a baby; do not submit an unscoped activity. |
| No history | Keep quick/manual entry available and show a tracker-specific empty message. |
| Invalid field/range | Keep entered values, identify the problem and do not call the create API. |
| Sleep timing warning | Explain the overlap/gap and require the user to confirm or correct it. |
| Offline create | Show the pending outbox record and retry state; avoid a duplicate when connectivity returns. |
| More-history failure | Keep already loaded rows and offer another load attempt. |
| External change during edit | Block save until the item is reloaded or the edit is abandoned. |
| Coach permission changed | Fail safely, explain that access changed and remove/disable further write actions. |
| Image upload failure | Preserve the rest of the nappy form/save state and allow a controlled retry. |
Platform API contract
| Method and path | Role |
|---|---|
GET /activities | List subject-authorized activity. Filters include familyUserId, babyId, type, ladderId, stageId, since, until, limit (maximum 100) and cursor. |
POST /activities | Create an idempotent activity from babyId, type, details, note, timeZone, optional activeTimerId and clientMutationId. |
PATCH /activities/:id | Correct an authorized activity while preserving actor-specific fields. |
DELETE /activities/:id | Delete an authorized activity. |
POST /files/signed-upload-url | Obtain a scoped upload URL for supported activity media. |
POST /files/signed-download-url | Resolve an authorized private image for display. |
The API validates the discriminated details schema for the selected type and ensures the baby, activity, ladder/stage and media all belong to the resolved family subject.
Timezone and data integrity
- New records carry the family/client IANA timezone and a server-derived local date.
- Changing the family timezone affects future day boundaries and display, but does not rewrite the timezone saved on historical records.
- Amounts retain their entered unit while analysis can normalize display to the family's preferred unit.
- Realtime refresh and idempotency solve different problems: refresh detects concurrent changes, while
clientMutationIdprevents duplicate creates after retries. - Tracking data remains accessible without premium; only Analysis is entitlement-gated.
Acceptance checklist
- Every tracker validates and persists its documented details for the selected baby.
- Quick actions produce reviewable records and timer-backed types hand off safely to timer review.
- History groups by family-local date, paginates without duplication and supports corrections.
- Offline create retries cannot make duplicate activities; edits/deletes are never falsely shown as queued.
- A stale edit cannot silently overwrite a realtime external change.
- Coach writes require current permission and preserve family-authored notes.
- Activity APIs reject cross-family babies, records, ladder stages and media.
Source evidence
mobile-web/src/routes/ActivityTrackingScreen.tsxmobile-web/src/timers/ActiveTimersContext.tsxmobile-web/src/offline/ActivityCreateOutboxContext.tsxmobile-web/src/realtime/use-resource-realtime-refresh.tsplatform/apps/api/src/routes/family-routes.tsplatform/apps/api/src/services/family-service.tsplatform/packages/shared/src/family.tsplatform/docs/multi-tenancy/06-existing-app-feature-inventory.md
