Document 02 · Current implementation

Data structure

The models the client currently reads, writes, derives, or persists.

Field names follow the TypeScript app model. API-only snake_case mappings are shown in the API reference.

1. Data ownership

StoreOwnsBehavior
Backend APIAccounts, memberships, children, interests, traits, screen read models, play sessions, scans, milestones, saved items, article reads, care queue, tracker copy, notifications, entitlements, devices, consents, jobs, support requests.Authoritative for signed-in shared data.
Device storageSession, tracker working copy, pending sync, timers, preferences, reading progress, avatar, photo consent, custom/tried foods, growth reference, trial-door markers.AsyncStorage on native, localStorage on web, memory in logic tests.
Bundled app dataActivities and reading content used by signed-out/preview paths, food list, milestone content, WHO growth standards.Ships with the app; not user data.
React memoryCurrent child, active tab, loaded screen models, modal/sheet state, draft interactions, current language.Lost on process restart unless mirrored in device/API storage.

2. Main relationships

erDiagram
  USER ||--o{ ACCOUNT_MEMBERSHIP : has
  ACCOUNT ||--o{ ACCOUNT_MEMBERSHIP : contains
  ACCOUNT ||--o{ CHILD : owns
  CHILD ||--o{ CHILD_INTEREST : has
  CHILD ||--o{ CHILD_TRAIT : has
  CHILD ||--o{ MILESTONE_OBSERVATION : records
  CHILD ||--o{ PLAY_SESSION : completes
  PLAY_SESSION ||--o| SESSION_FEEDBACK : receives
  CHILD ||--o{ SCAN : requests
  SCAN ||--o{ ACTIVITY_SUGGESTION : returns
  CHILD ||--o{ TRACKER_ENTRY : logs
  CHILD ||--o{ ARTICLE_READ : reads
  CHILD ||--o{ SAVED_ITEM : saves
  CHILD ||--o{ CARE_QUEUE_ITEM : receives
  ACCOUNT ||--o{ NOTIFICATION : receives
  ACCOUNT ||--|| ENTITLEMENTS : controls
  ACCOUNT ||--o{ DEVICE : registers
    

3. Identity and child profile

ModelFields used by the app
AuthSessionaccess_token, optional token metadata, user, active account.
Userid, email, given/family name, display name, locale and status fields returned by the server.
Accountid, name/status and active membership context. Sent as X-Account-Id.
MeProfileuser plus account memberships; the active membership refreshes the session's user/account snapshot.
ChildRecordid, name, preferred name, birth date, sex/gender value, locale/time zone, status, timestamps, and server-provided profile fields.
ChildCreateInputName, optional preferred name, birth date, optional sex, locale, and time zone.
RegisterOnboardingPayloadChild profile, four-area milestone answers, interests, optional traits, and onboarding metadata used during registration/submission.
ChildInterestRecordRecord id, child id, interest code/label, optional custom value, timestamps.
ChildTraitRecordRecord id, child id, trait code/value and timestamps.

4. Screen and content models

ModelPurpose and notable fields
HomeScreenDataChild summary, welcome copy, suggested activities, saved preview, updates data, and related Home display sections.
PortraitScreenDataChild identity, developmental domains/bands, skill pot, interests, streak and server-calculated portrait content.
ActivitySummaryActivity id, title, description, domain/category, age/setting, materials, safety, instructions, and optional target milestone/suggestion links.
PlaySessionRecordSession id, child/activity/suggestion references, context, start/end/completed state, timestamps, and optional feedback.
ResourceContentStable local id, optional server apiId, title, teaser/body/read sections, category, age range, debut/pin/display rules.
ResourceProgressstatus: new|read, saved, optional finishedInSession.
CareQueueItemQueue id/type/status/order, child scope, payload and actions for feedback, resource, or milestone work.
AppNotificationNotification id/type/title/body, timestamps, viewed/dismissed state, child context, and action payload.
NotificationPreferencesPush/email channel switches returned and updated as one preference object.

5. Tracker model

Every tracker row shares the following envelope. Detail blocks are present according to kind.

TrackerEntry {
  id, kind, childId, occurredAt,
  endedAt?, durationSeconds?, note?,
  clientEventId, createdAt,
  pendingSync, syncedId?,
  feeding?, sleep?, diaper?, measurement?, health?, pump?
}
BlockFields
feedingmethod, amountMl, foodItems[], mealType, reactedTo[], moodAfter. Nursing duration can use common duration plus side-specific data in the local model.
sleepkind, quality, location, wakeCount, moodBefore, moodAfter, sleptThrough.
diaperkind, consistency, color, hasRash, inPotty.
measurementkind: weight|height|head, numeric value, canonical unit: kg|cm.
healthkind, description, temperatureC. Supported in storage/API mapping; no current Quick Log entry point.
pumpleftMl, rightMl, leftSeconds, rightSeconds, totalMl.

kind is feeding | sleep | diaper | measurement | health | pump. New rows use a client event id for idempotency. Synced rows retain the server id. A deleted synced row creates a tombstone until the server acknowledges it.

6. Milestones, access, and asynchronous work

ModelFields used
MilestoneAnsweryes | not_yet | unanswered in local interaction/journal; server writes carry milestone id or code, value and observation metadata.
MilestoneJournalEntrymilestoneId, answer, ISO answered_at. Append-only on the device.
EntitlementsPlan/tier display, active/trial dates, features: Record<string, boolean>, limits: Record<string, number>, promotions, optional payments switch. -1 means unlimited.
Jobid, kind, status, optional poll_after, progress, result and error. Used after child deletion.
DeviceDevice id, platform, Expo push token, locale/time zone and app/device metadata used for notification registration.
SupportRequestInputtype, message, optional child_id, current_url, and client_context. Types: bug, feedback, account/subscription, feature request, other.

7. Device persistence keys

KeyStored shapeScope
buzzbaby.authSession.v1AuthSessionDevice/browser
buzzbaby.authMethod.v1email | google | appleDevice/browser
buzzbaby.pushDevice.v1Registered server device idDevice
buzzbaby.resourceProgress.v1.<childId>{version, session, cards: {resourceId: {status, saved, finishedInSession?}}}Child
buzzbaby.tracker.v1{version, entries[], deletions?: [{syncedId, deletedAt}]}All children on device; rows contain child id
buzzbaby.trackerTimers.v1{version, timers: {key: {startedAt?, accumulatedMs, entryPointId?}}}Device
buzzbaby.trackerPrefs.v1{version, preferences: {hiddenGroups, hiddenEntryPoints, entryMode, units, hiddenBottleTypes}}Device/family
buzzbaby.customFoods.v1{version, foods[], hidden?}Device/family
buzzbaby.triedFoods.v1.<childId>{version, foods[]}Child
buzzbaby.growthProfileSex.v1.<childId>{version, sex: boys|girls|null}Child
buzzbaby.avatarChoice.v1{avatarId?, photo?}; photo is native file URI or downsized web data URIDevice; not child-keyed
privacy.photo_scan_consent.<accountId>granted | revoked | unsetAccount; unsuffixed while signed out
milestones.journal.<childId>MilestoneJournalEntry[]Child
buzzbaby.googleForceAccountPicker.v1BooleanDevice/browser
monetization.trial_door_resolved.event.<eventId>BooleanBackend event on device
monetization.trial_door_pending_event.v1{eventId, accountId}Device

Versioned files are validated before use. Unknown versions normally reset that local feature's state; tracker data is handled especially defensively because it contains caregiver-entered records.

8. Data movement

flowchart LR
  UI[Screen and sheet] --> CTX[App state / feature hooks]
  CTX --> SVC[Business services]
  SVC --> DATA[Repositories]
  DATA --> API[(Backend API)]
  SVC --> STORE[(Device storage)]
  BUNDLE[(Bundled content)] --> SVC
  API --> DATA --> CTX --> UI
  STORE --> SVC