Document 03 · Reverse-engineered implementation map

Frontend and backend architecture

Where each flow starts, where its business decisions are made, how the client crosses the API boundary, and which system owns the durable result.

Evidence boundary: frontend statements were verified from executable code reachable from index.ts and App.tsx. Backend statements were then re-verified against the copied buzzbaby-be-main Fastify service, its route registry, handlers, services, Prisma schema, migrations, and OpenAPI document. The analysis-only SQL under appAnalysis/postgresql/ is not production backend code.
1Expo client for iOS, Android, and web
5state-routed primary tabs
3client rule/IO layers: service, data, config
98OpenAPI operations registered
93real handlers; 5 explicit 501 stubs
54Prisma models across five server schemas (+ AI object types)

1. How to read this document

Evidence labelMeaningWhat may safely be concluded
Verified clientThe file is in this checkout and is imported by the running app or by a reachable module.The described UI, orchestration, calculation, request mapping, and local persistence are implemented in the current client snapshot.
Verified backendThe copied backend file was inspected directly in buzzbaby-be-main.The described route, handler, service, auth/tenant boundary, and persistence behavior is present in this backend snapshot.
API boundaryThe client constructs and calls the endpoint in current code.The request/response behavior expected by the app is implemented client-side. Internal server logic cannot be proven from this checkout alone.
Keep the database views separate: appAnalysis/postgresql/ is a standalone analysis schema built from app data. It helps query the milestone/tracker corpus but does not represent or migrate the backend database. Production persistence is defined by buzzbaby-be-main/prisma/schema.prisma plus buzzbaby-be-main/db/migrations/.

2. Frontend/backend boundary at a glance

flowchart LR
  subgraph FE[Frontend - this repository]
    UI[React Native screens and sheets]
    ORCH[App.tsx and AppStateContext orchestration]
    RULES[src/services business and presentation rules]
    REPO[src/data repositories and DTO mappers]
    LOCAL[(AsyncStorage or localStorage)]
    UI --> ORCH
    ORCH --> RULES
    ORCH --> REPO
    RULES --> REPO
    RULES <--> LOCAL
  end
  REPO -->|authorized fetch and JSON| HTTP[REST API]
  subgraph BE[Backend - separate sb-app-be repository]
    HTTP --> ROUTER[OpenAPI route validation and handler registry]
    ROUTER --> HANDLER[Handlers and server services]
    HANDLER --> DB[(PostgreSQL and server state)]
  end
  SDK[Apple, Google, Expo Push, RevenueCat, Sentry, PostHog] <--> FE
    

3. Runtime stack

ConcernImplemented choiceCode location
ApplicationExpo SDK 57, React 19, React Native 0.86, TypeScript.package.json, app.json
EntryInitialize crash reporting, then register the root React component.index.tssrc/services/crashReporting.tsApp.tsx
NavigationReact state; five tabs plus modal, sheet, play-state, and onboarding-state substitutions. No Expo Router or React Navigation.App.tsx, src/app/constants.ts
Shared stateA large composition context plus feature-local state and subscribed module stores.src/app/AppStateContext.tsx, src/services/*
NetworkREST over fetch with one base URL, endpoint registry, bearer token, and account header.src/config/api.ts, src/config/apiEndpoints.ts, src/data/authRepository.ts
Device persistenceAsyncStorage on native, localStorage on web, injectable memory storage in tests.src/data/deviceStorage.ts
Native/external SDKsImage picker/manipulation, Apple and Google identity, Expo notifications, RevenueCat, Sentry, and PostHog.src/services/*Auth.ts, pushNotifications.ts, purchasesService.ts, crashReporting.ts, analytics.ts

4. Frontend code map

flowchart TD
  ENTRY[index.ts] --> APP[App.tsx]
  APP --> SCREENS[src/screens and src/features]
  APP --> CONTEXT[src/app/AppStateContext.tsx]
  SCREENS --> COMPONENTS[src/components]
  APP --> SERVICES[src/services]
  SCREENS --> SERVICES
  APP --> DATA[src/data]
  SERVICES --> DATA
  DATA --> CONFIG[src/config]
  DATA --> TYPES[src/types]
  SERVICES --> TYPES
    
Frontend layerResponsibility in the implemented appRepresentative code
App.tsx and src/app/Composition root. Owns app/onboarding phase, active tab, active child, loaded server read models, cross-screen callbacks, overlays, auth reaction, and flow handoffs.App.tsx, AppStateContext.tsx, updatesQueueFlow.ts, playTabRouting.ts
src/features/onboarding/Onboarding presentation and auth form surfaces. The visible step flow is controlled by state passed from App.tsx.OnboardingFlow.tsx, EmailAuthForm.tsx, provider sign-in buttons
src/screens/The five primary product screens and app-wide modals/sheets. Screen-local interaction state belongs here.HomeScreen.tsx, PortraitScreen.tsx, PlayScreen.tsx, TrackerScreen.tsx, ResourcesScreen.tsx
src/components/Reusable UI and interaction grammar. Components accept data/callbacks and should not decide feature-specific business policy.appChrome.tsx, AppButton.tsx, activity/resource headers, tracker icon primitives
src/providers/Reactive hooks around cross-cutting stores. In the current checkout these are entitlement and payment-enabled hooks, not a complete auth/locale provider layer.useEntitlements.ts, usePaymentsEnabled.ts
src/services/Client business rules and reusable calculations: selection, ranking, validation, gates, reports, local stores, and SDK seams.milestoneEngine.ts, activityPlanner.ts, trackerStore.ts, trackerInsights.ts, resourceProgress.ts, childGate.ts
src/data/HTTP repositories, authorization transport, DTO conversion, bundled content access, and device-storage abstraction.authRepository.ts, screenRepository.ts, trackerRepository.ts, contentMappers.ts, deviceStorage.ts
src/config/API URL resolution and stable client configuration/domain constants.api.ts, apiEndpoints.ts, domains.ts
src/types/Shared TypeScript contracts without decision-making logic.auth.ts, screens.ts, activity.ts, notifications.ts

5. Backend code map

The copied backend is a Fastify/TypeScript service in buzzbaby-be-main. It loads openapi/initial-api.yaml, turns every operation into a validated route, looks up the operation in src/handlers/index.ts, and sends unimplemented operations through an explicit 501 not_implemented stub. All paths in this section are relative to buzzbaby-be-main/.

Backend concernVerified server codeHow it implements the flow
Route registration and validationbuzzbaby-be-main/src/openapi/registerRoutes.ts, src/openapi/spec.ts, src/openapi/toFastifySchema.tsDereferences the YAML spec, converts paths to Fastify routes, applies body/query/header schemas, attaches operation-specific rate limits, and selects real handler versus named 501 stub. Current registry comparison: 98 operations, 93 handlers, 5 stubs (createInvite, dismissSuggestion, ingestEvents, ingestFeedback, getMedia).
Server boot and middlewaresrc/app.ts, src/server.tsRegisters CORS, global/per-route rate limits, Prisma, JWT auth, tenant resolution, entitlements, push sweeper, health check, centralized request logging, and OpenAPI routes.
Authentication and identitysrc/handlers/auth.ts, src/handlers/identity.ts, src/plugins/auth.ts, src/lib/password.ts, src/lib/googleIdToken.ts, src/lib/appleIdentityToken.tsSupports password auth in local HS256 mode and Google/Apple token exchange; verifies bearer JWTs (JWKS in deployed mode), creates/updates users/accounts, persists devices/consents, and deletes account data.
Tenant isolationsrc/plugins/tenant.tsResolves membership from X-Account-Id, caches the tenant on the request, runs protected queries in withTenant transactions with app.current_account_id, and keeps explicit account predicates alongside PostgreSQL RLS.
Entitlements and enforcementsrc/plugins/entitlements.ts, src/services/entitlements.ts, src/services/entitlementGate.ts, src/handlers/entitlements.tsResolves account tier/features/limits once per request, then supports feature checks, quotas, rate consumption, and server-side clamps for child, scan, saved-item, history, and billing flows.
Home/Portrait/Report read modelssrc/handlers/readModels.ts, src/services/resourceShelf.ts, src/services/scanContext.tsRuns tenant-scoped Prisma queries, computes area/skill progress, next skills, activity/resource shelves, daily plan/spark data, and serializes the exact client read-model envelopes.
Care queue and updatessrc/handlers/careQueue.tsBuilds actionable queue items from milestone/resource/session state, removes/resolves completed items, and applies queue actions inside tenant-scoped transactions.
Trackersrc/handlers/tracker.ts, db/migrations/0009_tracker_client_gaps.sqlUses raw SQL (tracker tables are intentionally not Prisma-modeled) for a six-kind union timeline; validates nested blocks, batches/deduplicates by client_event_id, supports create/update/delete/day totals, and persists pump/sleep/solids/potty fields added by migration.
Milestones and assessmentssrc/handlers/framework.ts, src/handlers/assessments.ts, src/handlers/growth.ts, src/handlers/onboarding.tsServes framework content, creates/submits/completes assessments, persists child milestone observations, and recomputes area/skill rollups consumed by Portrait.
Activities, scans, and sessionssrc/handlers/activities.ts, src/handlers/scans.ts, src/handlers/sessions.ts; src/services/openaiVision.ts, openaiActivity.ts, scanPrompt.ts, scanContext.tsServes activity catalog entries; sends room photos to OpenAI Responses vision, stores detections/suggestions without storing the raw photo, applies scan/regeneration gates, and persists play sessions/feedback.
Resources and saved itemssrc/handlers/library.ts, src/services/resourceShelf.tsLists/creates/deletes polymorphic saved items, embeds article/activity summaries, lists and marks article reads, and supplies resource shelves through the Home read model.
Notifications and pushsrc/handlers/notifications.ts, src/services/notifications.ts, src/services/pushDelivery.tsStores event types/subscriptions/settings, renders feed rows, marks viewed/dismissed state, and sweeps pending Expo push deliveries/receipts.
Billing, jobs, and supportsrc/handlers/billing.ts, src/handlers/jobs.ts, src/handlers/support.ts, src/services/supportEmail.ts, src/handlers/progressReports.tsConsumes RevenueCat webhooks idempotently, polls asynchronous jobs/reports, sends support requests through server-owned SES, and schedules progress-report work.
Database boundarybuzzbaby-be-main/prisma/schema.prisma, db/migrations/, src/plugins/prisma.tsPrisma models 54 server entities across core/growth/content/scan/notification schemas; the tracked migration set currently contains 27 files. Tracker remains raw SQL because its tables are outside the Prisma model.

Actual backend request pipeline

flowchart TD
  REQ[HTTP request] --> FASTIFY[Fastify app.ts]
  FASTIFY --> CORS[CORS and rate limit]
  CORS --> SPEC[Spec-driven OpenAPI route]
  SPEC --> VALIDATE[AJV params, query, headers, body]
  VALIDATE --> AUTH{bearerAuth?}
  AUTH -- yes --> JWT[plugins/auth.ts JWT verify]
  AUTH -- no --> REGISTRY
  JWT --> REGISTRY[handlers/index.ts lookup]
  REGISTRY -- missing --> STUB[501 not_implemented]
  REGISTRY -- found --> TENANT[resolveTenant and optional gate]
  TENANT --> HANDLER[domain handler]
  HANDLER --> TX[withTenant transaction and explicit account predicate]
  TX --> PRISMA[Prisma or tracker raw SQL]
  PRISMA --> DB[(PostgreSQL schemas and migrations)]
  HANDLER --> EXTERNAL[OpenAI, Expo Push, SES, Apple/Google JWKS]
  VALIDATE --> ERR[plugins/errorHandler.ts RFC 9457 problem]
  HANDLER --> ERR
  DB --> RESP[JSON envelope]
  RESP --> CLIENT[src/data repository mapper]
    

6. Startup, authentication, and child hydration

sequenceDiagram
  participant Entry as index.ts
  participant App as App.tsx
  participant Auth as authRepository
  participant ScreenRepo as screenRepository
  participant API as Backend REST API
  participant Local as Device storage and module stores
  Entry->>Entry: initialize Sentry
  Entry->>App: register root component
  App->>Auth: read persisted AuthSession
  App->>Local: begin local feature hydration
  alt signed-in session
    App->>API: GET /v1/me and /v1/children as needed
    API-->>App: account and children
    App->>App: adoptAccountChild and reset prior child state
    par signed-in read models
      App->>ScreenRepo: loadSignedInScreens(childId)
      ScreenRepo->>API: GET home, portrait, completed sessions, care queue
    and secondary account/child state
      App->>API: notifications, entitlements, config, milestone observations
    and hybrid stores
      App->>Local: begin child resource/tracker/growth sessions
      App->>API: article reads, saved items, tracker entries
    end
    API-->>App: typed responses
    App->>App: map and publish through AppStateContext
  else signed out
    App->>App: render onboarding or localhost preview fixture path
  end
    

Frontend decisions: initial phase, active tab, active child adoption, resetting cross-child state, loading concurrency, preview fixtures, and error/empty presentation. Backend decisions: authenticated identity, available children, read-model content, queue state, entitlements, and durable user records.

7. Flow-by-flow implementation ownership

This is the shortest map from a product flow to the code that actually executes it. In the table, frontend paths are relative to the app root; backend paths are relative to buzzbaby-be-main/.

FlowFrontend UI and orchestrationClient business logicClient repository and APIBackend responsibility / recorded codeDurable authority
Email, Google, or Apple sign-inOnboardingFlow.tsx, auth forms/buttons, App.tsx handleAuthSuccessemailAuth.ts, providerSignIn.ts, googleAuth.ts, appleAuth.ts, postAuthNavigation.tsauthRepository.tsPOST /v1/auth/*, GET /v1/mebuzzbaby-be-main/src/handlers/auth.ts validates password/provider identities, creates/finds the user/account, and issues a local HS256 token; src/plugins/auth.ts verifies bearer JWTs at ingress.Backend; session token is cached on device.
Onboarding and first childOnboardingFlow.tsx; App.tsx goNextOnboarding, finishAuthenticatedOnboardingmilestoneEngine.ts selects questions; childAge.ts computes age; onboardingRegister.ts builds the payloadchildProfileRepository.tsPOST /v1/onboarding; registration may carry onboarding databuzzbaby-be-main/src/handlers/onboarding.ts writes child/profile/interest/trait/assessment data in tenant scope; assessments.ts handles assessment responses/completion.Backend after authentication; pre-submit answers live in React memory.
Switch/add/edit/delete childProfileModal.tsx, AddChildModal.tsx, ProfileEditModal.tsx; App.tsx adoptAccountChildchildGate.ts, childGender.ts, mockProfileFactory.ts, profileInterestDisplay.tschildProfileRepository.ts → children/interests/traits/jobs endpointshandlers/children.ts persists child/caregiver changes; handlers/childProfile.ts persists interests/traits; handlers/jobs.ts exposes asynchronous delete status; services/entitlementGate.ts enforces server quotas.Backend; selected child is current React state.
Home dashboardHomeScreen.tsx, App.tsxhomeJournalTime.ts, app-level activity/resource mapping, saved/read storesscreenRepository.ts fetchHomeScreenGET /v1/children/{id}/homeCompose the signed-in Home read model. Recorded starting point: handlers/readModels.ts.Backend for signed-in content; local state for transient presentation.
Updates bell and queueHomeScreen.tsx, Updates tray wired in App.tsxupdatesQueueFlow.ts determines renderable counts/routes; fixture helpers are localhost-onlyscreenRepository.ts care-queue calls; notificationsRepository.ts feed/preferences callsGenerate/resolve queue items in handlers/careQueue.ts; notification state in handlers/notifications.ts.Backend for queue and feed status; client owns badge combination and presentation.
Portrait and milestone editingPortraitScreen.tsx, WebDomainSheet.tsx, milestone modal; save handlers in App.tsxmilestoneEngine.ts maps domains and calculates star progress; portraitStar.ts hydrates; skillPot.ts; milestoneJournal.tsscreenRepository.ts portrait read; growthRepository.ts list/PUT/DELETE milestone observationshandlers/readModels.ts composes Portrait/skill-pot data; handlers/growth.ts persists observations and recomputes area/skill rollups; handlers/framework.ts serves framework definitions.Backend observation/read model plus an append-only local answer journal.
Play from library or milestonePlayScreen.tsx; session lifecycle callbacks in App.tsxactivityPlanner.ts ranks the available age-safe set; activityPresentation.ts; feedback mapping in playRepository.tscontentRepository.ts activities; playRepository.ts create/complete/feedback session callshandlers/activities.ts serves catalog rows; handlers/sessions.ts persists play sessions and feedback; handlers/readModels.ts includes server-composed suggestions.Backend for signed-in catalog/session history; React state for active guide.
Play from a room photoPlayScreen.tsx, PhotoConsentSheet.tsx; capture/generation handlers in App.tsxphotoConsent.ts, scanPhoto.ts, scanGate.ts, customActivityGuardrails.tsscanRepository.ts → create/poll scan, detections, suggestions; consentRepository.tshandlers/scans.ts orchestrates scan state, quota, persistence, and polling; services/openaiVision.ts analyzes the image; services/openaiActivity.ts generates suggestions; services/scanContext.ts/scanPrompt.ts build child-fit context. Raw images are not stored.Backend for scan job/results; device/React memory for consent gate and captured image preparation.
Tracker log, edit, report, and syncTrackerScreen.tsx and src/screens/tracker/* sheets/reportstrackerEntryMapping.ts, trackerStore.ts, trackerTimers.ts, trackerInsights.ts, growthReport.ts, trackerExport.tstrackerRepository.ts → list, sync, PATCH, DELETEbuzzbaby-be-main/src/handlers/tracker.ts validates, deduplicates, persists, updates, and deletes server rows.Hybrid: device working copy is immediate; backend is the signed-in durable/shared copy.
Resources, reading, and savesResourcesScreen.tsx, ResourceReadModal.tsx, ResourceReadingBookModal.tsx, ResourceTopicModal.tsxresourceProgress.ts owns new/read/saved/session semantics; resourcePersistence.ts mirrors completed reads; resourceDisplay.tsscreenRepository.ts gets signed-in resources via Home; resourceProgressRepository.ts article reads; libraryRepository.ts saved itemshandlers/readModels.ts selects the Home resource shelf; handlers/library.ts persists saved items and article reads; services/resourceShelf.ts ranks the server shelf.Hybrid: local state drives instant/session UX; backend stores signed-in reads and remote saves.
Entitlements and purchasesrc/screens/paywall/*, add-child/save/scan gate surfacespaymentsGate.ts, childGate.ts, scanGate.ts, purchasesService.ts, trialDoor.tsentitlementsRepository.ts, clientConfigRepository.ts → entitlements/config; RevenueCat SDK outside RESThandlers/entitlements.ts reads account grants; services/entitlementGate.ts enforces feature/quota/rate decisions; handlers/billing.ts consumes idempotent RevenueCat webhooks.Backend entitlement state; RevenueCat/store supplies transaction events. Client never self-grants Plus.
Push and notification preferencesProfileModal.tsx, Home Updates tray, App.tsxpushNotifications.ts, pushRegistration.ts, notificationDripRules.tsnotificationsRepository.ts, deviceRepository.ts → notifications/preferences/deviceshandlers/notifications.ts and services/notifications.ts render/raise feed events; services/pushDelivery.ts sweeps Expo delivery; device routes are in handlers/identity.ts.Backend feed/preferences/device record; OS controls permission; client owns opt-in timing.
Support and account deletionProfileModal.tsx, DeleteAccountModal.tsxsupportRequestCopy.ts, logout cleanup servicessupportRepository.tsPOST /v1/support/requests; accountDeletion.tsDELETE /v1/mehandlers/support.ts validates and sends support mail through services/supportEmail.ts; handlers/identity.ts deletes the account in a transaction and revokes Apple refresh tokens when configured.Backend; client clears its local session/state after deletion/logout.

8. Where the important business rules live

Business decisionPrimary ownerHow it is implementedServer role
Which onboarding milestone questions appearFrontend servicesrc/services/milestoneEngine.tsCalculates age, applies logic bands/caps, groups four assessment areas, and formats the rows consumed by onboarding.Receives the resulting assessment payload and persists it.
Which primary screen is visibleFrontend compositionApp.tsx, src/app/constants.tsState selects one of five tabs or a modal/sheet/flow state. Localhost query parameters only initialize QA paths.No production navigation ownership.
What Home and Portrait contain for a signed-in childBackend read modelThe client displays/maps server HomeScreenData and PortraitScreenData.Chooses and composes signed-in read-model content; recorded entry is handlers/readModels.ts.
Portrait star calculation shown in the clientFrontend servicemilestoneEngine.ts, hydrated by portraitStar.tsMaps local and remote checks into five domains and calculates current/behind/beyond visual progress.Supplies milestone observations and Portrait/skill-pot inputs.
Ordering of available Play activitiesFrontend serviceactivityPlanner.tsRanks the already available age-safe activity set using milestone/domain need. It does not authorize server-only content.Serves the remote activity/suggestion pool and persists sessions.
Room-scan quota and generated resultBackend enforcement with client UX gatescanGate.ts interprets offline/402 failures and chooses the paywall/retry presentation.Enforces quota and produces scan detections/suggestions.
Tracker entry validity, immediate history, totals, and reportsFrontend servicesSheets map inputs through trackerEntryMapping.ts; trackerStore.ts persists; trackerInsights.ts and growth services calculate reports.Validates API DTOs, deduplicates client event IDs, and provides durable/shared storage.
Resource new/read/saved/session behaviorFrontend serviceresourceProgress.tsDetermines what is new/read, what stays visible this session, and what appears on the Home shelf.Provides article content and persists completed reads/saved objects for signed-in users.
Care-queue item generation and lifecycleBackend generation, frontend rendering rulesupdatesQueueFlow.ts combines queue and notification counts, hides non-renderable activity feedback, and routes CTAs.careQueue.ts creates items and applies complete/later/clear-style actions.
Plan access and quotasBackend authority, frontend capability gatesUI asks can(), limitOf(), payment switch, and error classifiers; it does not branch on a plan name.Returns entitlements/config and must enforce quotas even if client checks are bypassed.
Push pacingShared contractnotificationDripRules.ts is an executable client-side rule/test reference; permission and registration are client-side.The actual scheduler/delivery service must enforce the production pacing.

9. Detailed hybrid flow: Tracker

sequenceDiagram
  participant UI as Tracker sheet
  participant Map as trackerEntryMapping
  participant Store as trackerStore
  participant Disk as Device storage
  participant Repo as trackerRepository
  participant API as Backend tracker handler
  UI->>Map: entered values
  Map-->>UI: normalized TrackerEntry
  UI->>Store: add, update, or delete
  Store->>Disk: persist working copy or deletion tombstone
  Store-->>UI: notify subscribers immediately
  alt new local entry
    Store->>Repo: pending create batch
    Repo->>API: POST /children/{id}/tracker/sync
  else correction to synced row
    Store->>Repo: syncedId plus changed entry
    Repo->>API: PATCH /tracker/entries/{id}
  else delete synced row
    Store->>Repo: persisted tombstone
    Repo->>API: DELETE /tracker/entries/{id}
  end
  API-->>Repo: accepted/duplicate/server row or error
  Repo->>Store: acknowledge or retain pending mutation
  Store->>Disk: persist reconciled state
    

The frontend does not wait for the network before closing a sheet. That is an intentional business/UX contract: device state is the working copy, while failed server writes remain pending. Corrections must use PATCH; replaying them through sync can be treated as a duplicate. Deletes need tombstones so a later server load cannot resurrect the row.

10. Detailed hybrid flow: Resources

sequenceDiagram
  participant UI as Resource reader
  participant Progress as resourceProgress
  participant Disk as Device storage
  participant Repo as Resource repositories
  participant API as Backend
  UI->>Progress: open, finish, or toggle save
  Progress->>Disk: update child-scoped progress immediately
  Progress-->>UI: notify resource and Home shelf subscribers
  alt completed remote article
    Progress->>Repo: markResourceReadForChild
    Repo->>API: PUT /children/{id}/article-reads/{articleId}
  else save remote article/activity
    Progress->>Repo: createSavedArticle or createSavedActivity
    Repo->>API: POST /children/{id}/saved-items
  else unsave remote item
    Progress->>Repo: deleteSavedItem
    Repo->>API: DELETE /saved-items/{id}
  else local-only content id
    Progress-->>Disk: remain local because backend has no object reference
  end
    

Signed-in resource content currently arrives inside the Home read model, not from the configured standalone /v1/resources path. The local session rule intentionally lets a just-finished card keep its place until the next launch, even after the completion has been mirrored to the API.

11. Detailed server flow: room-photo Play

sequenceDiagram
  participant UI as PlayScreen and App.tsx
  participant Local as Client services
  participant Repo as scanRepository/playRepository
  participant API as Backend
  UI->>Local: check photo consent and request OS camera permission
  Local-->>UI: permitted photo
  UI->>Local: resize/compress/encode photo and apply guardrails
  UI->>Repo: createSceneScan with prompt/tags
  Repo->>API: POST /children/{id}/scans
  loop until terminal or timeout
    Repo->>API: GET scan status/suggestions/detections
    API-->>Repo: processing or terminal result
  end
  Repo-->>UI: mapped activity cards
  UI->>Repo: start selected activity
  Repo->>API: POST /children/{id}/sessions
  UI->>Repo: finish and submit feedback
  Repo->>API: PATCH session and PUT feedback
    

The client owns consent timing, media preparation, timeout/error classification, and the visible activity flow. The backend owns image processing, generated suggestions, quota enforcement, and durable session/feedback records.

12. Milestone data path and current split

flowchart TD
  CORPUS[(Bundled consolidatedMilestones.json)] --> ENGINE[milestoneEngine selection and star rules]
  API[(Backend milestone observations and Portrait)] --> HYDRATE[portraitStar and DTO mapping]
  ENGINE --> ANSWERS[App.tsx answer map]
  HYDRATE --> ANSWERS
  ANSWERS --> PORTRAIT[PortraitScreen and WebDomainSheet]
  PORTRAIT --> JOURNAL[(Local append-only milestone journal)]
  PORTRAIT --> GROWTH[growthRepository PUT or DELETE]
  GROWTH --> API
  API --> REFRESH[Refresh Portrait and milestone hydration]
  REFRESH --> HYDRATE
    

The bundled corpus defines the questionnaire and client star math; backend observations make signed-in answers survive reload and feed the server read model. The separate milestone analysis documents the exact selection/status mapping and the currently inconsistent write paths across onboarding, Portrait, and Home Updates.

13. Network implementation

flowchart LR
  CALLER[App, service, or screen] --> REPO[Typed data repository]
  REPO --> ENDPOINT[getApiEndpointUrl]
  ENDPOINT --> ENV[EXPO_PUBLIC_API_BASE_URL plus path override]
  REPO --> AUTH[authorizedFetch]
  AUTH --> HEADERS[Accept, Bearer token, X-Account-Id]
  AUTH --> FETCH[fetch with no-store]
  FETCH --> EXPECT[Explicit expected HTTP status]
  EXPECT -- success --> MAP[Envelope and DTO mapping]
  EXPECT -- problem --> ERROR[AuthApiError]
  ERROR -- invalid or expired session --> CLEAR[Clear local auth session]
    

14. State and persistence ownership

State kindOwnerExamplesLifetime
Composition/navigationApp.tsxPhase, tab, onboarding step, active child, active overlays, Play flow stateReact process unless reconstructed
Shared screen data/actionsAppStateContextHome/Portrait/queue/session models and cross-screen callbacksReact process; refetched after auth/child changes
Subscribed local storessrc/services/Tracker, timers, resource progress, custom/tried foods, growth profile, paywall controller stateModule memory, often mirrored to device storage
Device cache/working copydeviceStorage.ts consumersAuth session, pending tracker mutations, timers, preferences, avatar URI/data, local consent, milestone journalAcross launches on one device/browser
Signed-in truthBackend APIAccount, children, assessments, read models, sessions, scans, tracker copy, saved/read records, queue, notifications, entitlementsAcross devices and sessions
Bundled reference contentsrc/data/*.json and content modulesMilestone corpus, onboarding options, food list, growth standards, signed-out/preview contentApp build version

15. Where to make a change

If the requested change is…Start hereThen verify
Visual layout or local interaction on one screenThe relevant src/screens/*.tsx or src/features/*.tsxWhether the behavior belongs in an existing shared component or service
A rule reused across screenssrc/services/Callers, focused *.test.ts, and the owning product contract
A request/response shapesrc/types/, the relevant src/data/*Repository.ts, and docs/api/README.mdBackend OpenAPI and handler registry in sb-app-be
A signed-in content-selection or durable enforcement ruleThe backend handler/service after opening the backend checkoutClient DTO mapping, loading/error states, and server tests
A local-first/offline behaviorThe feature service/store and src/data/deviceStorage.tsMerge, retry, version-migration, and cross-child behavior
An entitlement or quotaBackend entitlement/config/enforcementClient capability gate and 402 handling; never rely only on the UI

16. Current structural facts and risks

These are present-state implementation observations, not a proposed roadmap.

17. Verification

The architecture map was checked against the current app entry/composition files, layer READMEs, repositories, services, screen imports, endpoint registry, all backend handler/service modules, prisma/schema.prisma, db/migrations/, and openapi/initial-api.yaml. No product source was changed.

npm run typecheck
npm run lint
npm run test:logic

The app checks could not run in this checkout because its node_modules is absent (tsc and eslint were not found). The backend has the corresponding commands npm run typecheck and npm run smoke:routes; run them after installing dependencies when validating code changes.