Help centre Families Coaches Support

Littles Baby Tracker

Help for families and coaches

Site Tools


technical:features:22_family_activity_notifications

22 — Family activity notifications

Technical reference. For task-based help, see the corresponding user guide.
Documentation status: complete for the current implementation

Reviewed: 2026-07-21

Rollout: server, client and push gated; deployed values must be verified

Primary users: genuine subscribed coaches

Surfaces: coach admin portal, mobile coach workspace, platform API, realtime and optional native push

Purpose

Family activity notifications give a coach a focused feed of new activity logs created by families they currently support. The feed powers the coach bell badge, in-app toast, Unread / All / Muted views, per-family alert controls and deep links to the relevant tracker. Optional native push can announce that new family activity exists without placing family, baby or health details on the lock screen.

This is a coach alert feature. It does not notify the family and it does not replace the family's activity record, the caseload “new logs” marker or the coach's clinical review workflow.

User outcomes

Coach need Outcome
Notice new family logs See an unread count on the coach bell and a realtime in-app toast while signed in.
Triage activity Review newest notifications grouped by creation date with family, baby, activity label and bounded summary.
Open the source context Deep-link to the selected family's tracker type and baby.
Pause interruptions Turn the global alert preference off while retaining activity in All.
Silence one family Mute that family's unread contribution while retaining its history in All and Muted.
Start fresh after a pause Resume or unmute without turning the paused backlog into new unread alerts.
Receive phone alerts Optionally enable generic push on a compatible registered mobile wrapper.

Entry points

Surface Route/location Function
Coach admin portal Bell → /notifications?tab=family Full feed, alert pause/resume, family mute, refresh and pagination.
Mobile coach dashboard Bell → /coach/notifications Full feed plus compatible phone-push controls.
Admin/mobile shell Bell badge and transient toast Show current unread total and announce newly invalidated eligible activities.
Notification card Stored route Open /coach/families/:familyId/track/:activityType?babyId=:babyId.
Native push Generic notification → /coach/notifications Open the notification feed; choose the detailed card from inside the authenticated app.

Eligibility boundary

An activity can appear only when all of these conditions are true at read time:

  1. the request belongs to a real coach session; ownerViewAsCoach is explicitly denied;
  2. the family has an active assignment to that coach;
  3. the assignment grants canViewLogs;
  4. the coach remains an active organization member;
  5. the organization is active/trialing and the coach subscription qualifies;
  6. the support entitlement still allows record access; and
  7. the activity was created by the family user, not by a coach acting in the family workspace.

The activity's createdAt must be at or after the assignment's assignedAt. Eligibility uses the time the record was created, not its back-dated occurredAt. A family can therefore log an older event after assignment and have that newly created record appear.

Paused support still allows record access and can remain eligible. Expired, revoked, canceled or inactive-billing access removes the family and its cards from notification results. A coach-authored edit or activity is not turned into a family notification merely because it belongs to that family.

Feed and filters

The API sorts newest first by createdAt and then activity ID, returning 30 cards by default with an opaque cursor. It accepts up to 100 per request. Current portals expose status filters and Load more; the API additionally accepts optional familyId and activityType filters.

View Included cards
Unread Only cards that pass every unread boundary, while global alerts are enabled and the family is not muted.
All Every eligible family-authored activity from the active assignment window, including read, globally paused and muted activity.
Muted / Muted families Eligible activity for currently muted families, plus controls to unmute each family.

Pausing alerts makes Unread empty and sets the shell count to zero; it does not delete data or empty All. Muting one family similarly removes that family's unread contribution but leaves its activity discoverable.

Unread calculation

Unread is derived, not stored on each activity. A card is unread only when:

  1. the coach's global preference is enabled;
  2. the family is not muted;
  3. createdAt >= assignedAt;
  4. createdAt is strictly after the global notifyAfter boundary, when present;
  5. createdAt is strictly after the family's notifyAfter boundary; and
  6. the activity sorts after the family's last-seen (createdAt, id) cursor.

The ID tie-breaker makes the cursor deterministic when two activities share the same timestamp.

Default and resume behavior

No global preference row means alerts off, push off, no unread count and no global notifyAfter. A missing family state means unmuted with notifyAfter equal to assignment time.

  1. First enabling alerts creates the coach preference with notifyAfter set to the current time.
  2. Re-enabling after a pause moves global notifyAfter to the current time.
  3. Unmuting a previously muted family moves that family's notifyAfter to the current time.
  4. Consequently, paused or muted backlog remains visible in All but does not suddenly become unread.

The platform feature route being enabled does not mean an individual coach has opted in. Per-coach alert and push preferences start off.

Mark-seen behavior

Opening an unread card optimistically clears every currently loaded unread card and summary count for the same family. In parallel, the client posts seen for that family. The platform finds the newest eligible family-authored activity in the assignment window and advances the family cursor to its (createdAt, id); this marks the family's current notification set read, not just the clicked activity.

If the request fails, the client restores its previous feed state where the screen remains mounted. The activity record itself is unchanged.

Notification seen state is separate from the general coach-family activity-review cursor used by the caseload and PATCH /coach/families/:familyId/activity-seen. Opening a notification does not automatically mark the family's logs reviewed in that separate workflow, and reviewing general logs does not advance this notification cursor.

Card presentation and privacy

Cards show family name, baby name, relative creation time, an activity label and a deliberately bounded summary:

Activity Label/summary behavior
Breastfeed Left/right side and elapsed duration when details validate.
Bottle Amount, unit and breast milk/formula.
Sleep Night sleep logged or Nap logged, with duration.
Nappy Wet, dirty or both.
Pumping Side, duration, amount and unit.
Medication Generic Medication logged only; medication name and dose are not summarized.
Solids Generic Solids logged and Reaction noted only for allergic reaction/accidental exposure.

When occurredAt differs from createdAt by at least 15 minutes in either direction, the card also shows the explicit occurred date/time. Feed grouping remains based on creation date.

The feed is authenticated coach data and does identify family/baby. Realtime invalidations do not carry that card content; clients refetch it through the authorized REST endpoint.

Global and family preferences

Global pause/resume

The portal and mobile settings update enabled. The UI applies an optimistic count/state change, then reloads the authoritative summary. Preference changes are broadcast as coach_activity_notification_state so another signed-in coach session can refresh.

Per-family mute

Every card offers Mute family alerts or Unmute family. Muting records mutedAt, removes the family's unread count and leaves its cards in All/Muted. Unmuting establishes a fresh family boundary as described above. Preference changes are audited without activity content.

Realtime behavior

Eligible activity creation publishes an activity resource invalidation. The admin and mobile coach shells then:

  1. refetch the unread summary rather than trusting broadcast content;
  2. update the bell badge;
  3. show a short in-app toast only for a newly invalidated, unread, unmuted card after initial hydration; and
  4. refresh the open feed when relevant activity or notification-state resources change.

The feed also refreshes on window focus/visibility return and offers a manual refresh. Realtime delivery is an acceleration path, not the source of truth; missed invalidations are repaired by these REST reloads.

Optional native push

Push is an additional opt-in on top of global alerts. It requires:

  1. the server notification and server push gates to be active;
  2. the coach's enabled and pushEnabled preferences;
  3. a mobile build whose push UI gate is active;
  4. native wrapper version 4.6.0 or newer;
  5. an enabled iOS/Android push device registration; and
  6. granted or provisional native permission with a valid FCM token/device identity.

Turning push on from mobile first asks the native wrapper for permission/registration, registers the device with the platform, and then saves pushEnabled. If permission is denied or the bridge/device cannot supply a usable registration, the preference is not enabled and the UI reports why.

Push content is intentionally generic:

  1. title: New family activity;
  2. body: Open Littles Baby Tracker to review.; and
  3. data: source/schema marker, activity ID and the fixed /coach/notifications route.

It does not contain family name, baby name, activity type, measurements, medication or notes. Before dispatch, the worker rechecks current access, family authorship, global/push preferences, mute and resume boundaries, device state and wrapper compatibility. Deliveries have at most three attempts; invalid/unregistered device tokens are disabled through the push sender's device handling.

Rollout gates

Layer Setting Default when absent Notes
Platform routes/feed COACH_ACTIVITY_NOTIFICATIONS_ENABLED Enabled, including production 1/true enables and 0/false disables. Any other configured value is treated as disabled. Disabled means routes are not registered.
Admin and mobile feed UI VITE_COACH_ACTIVITY_NOTIFICATIONS_ENABLED Enabled outside production; disabled in production Must be enabled in each production client build that should expose the bell/feed.
Platform push worker COACH_ACTIVITY_PUSH_ENABLED Enabled outside production; disabled in production Also requires the core platform notification gate. Explicit 1/true or 0/false wins.
Mobile push settings UI VITE_COACH_ACTIVITY_PUSH_ENABLED Enabled outside production; disabled in production Controls whether the phone setting is shown; wrapper compatibility is checked separately.
Native capability Wrapper version No compatible bridge below 4.6.0 Existing enabled preference can remain visible, but a new unsupported wrapper is told to update.
These are code defaults, not evidence of the values running in any deployed environment. Verify the API environment and the exact admin/mobile build variables before describing the feature or push as live.

Platform API contract

Method and path Role
GET /coach/activity-notifications List unread, all or muted cards with optional family/type filters, cursor and summary.
GET /coach/activity-notification-preferences Return coach global alert/push state.
PATCH /coach/activity-notification-preferences Change enabled and/or pushEnabled.
PATCH /coach/families/:familyId/activity-notification-preference Set that authorized assignment's muted state.
POST /coach/families/:familyId/activity-notifications/seen Advance the independent family notification seen cursor.
POST /push/devices Register/update the compatible native device used by optional push.

Failure and empty states

State Expected behavior
Alerts never enabled Zero unread; All can still show eligible post-assignment history.
Unread empty Explain that the coach is caught up.
All empty Explain that no eligible family activity has been logged.
Muted empty Explain that no families are muted.
Preference/mute update fails Roll back optimistic state and show the error.
Seen update fails Restore the prior notification summary where possible; do not mutate the activity.
Realtime unavailable Manual/focus refresh still reads authoritative REST state.
Push permission denied Keep push disabled and direct the coach to device settings.
Wrapper too old Keep feed available but show the 4.6.0 update requirement for push.
Access ended Omit/deny family activity without revealing inaccessible records.
Server feature disabled Notification routes are absent; production client gates should be aligned to avoid exposing a dead surface.

Acceptance checklist

  1. Only genuine coaches and currently authorized family assignments contribute cards.
  2. Coach-authored activities and pre-assignment records are excluded.
  3. Unread uses strict global/family resume boundaries plus a deterministic seen cursor.
  4. All remains useful while paused or muted; Unread and badge counts drop to zero appropriately.
  5. Resuming or unmuting does not create a backlog burst.
  6. Opening one unread card advances the family notification cursor and does not alter the general activity-review cursor.
  7. Presentation summaries disclose only the intended bounded fields; medication remains generic.
  8. Realtime payloads trigger authenticated refetch instead of carrying family content.
  9. Push is generic, opt-in, wrapper-gated and re-authorized at dispatch.
  10. Production rollout verifies server, each client build, push worker and wrapper/device gates independently.

Source evidence

Coach admin portal

  • admin-web/src/routes/FamilyActivityNotifications.tsx
  • admin-web/src/routes/NotificationsPanel.tsx
  • admin-web/src/hooks/useCoachActivityNotificationRealtime.ts
  • admin-web/src/components/AdminShell.tsx
  • admin-web/src/feature-flags.ts

Mobile web

  • mobile-web/src/components/CoachActivityNotificationsPanel.tsx
  • mobile-web/src/routes/CoachDashboard.tsx
  • mobile-web/src/App.tsx
  • mobile-web/src/feature-flags.ts
  • mobile-web/src/webview/native-messages.ts

Platform and contracts

  • platform/apps/api/src/routes/coach-activity-notification-routes.ts
  • platform/apps/api/src/routes/push-device-routes.ts
  • platform/apps/api/src/services/prisma-coach-activity-notification-service.ts
  • platform/apps/api/src/services/prisma-coach-activity-notification-access.ts
  • platform/apps/api/src/services/coach-activity-notification-service.ts
  • platform/apps/api/src/services/coach-activity-push-service.ts
  • platform/apps/api/src/feature-flags.ts
  • platform/packages/shared/src/coach-activity-notifications.ts
  • platform/packages/shared/src/push-devices.ts