Potty Coach
A native iOS potty-training coach for parents: calm, in-the-moment guidance from on-device rule engines — offline-first, three languages, zero shame by design.
- Role
- Pro eMarketing — design, build, ops
- Timeline
- 2026 · submission pending
- Stack
- Expo SDK 56React NativeTypeScript strictSQLite (offline-first)ZustandSupabase Edge FunctionsClaude HaikuRevenueCat (staged)
Potty training is a two-week stretch where calm, specific advice matters most and is hardest to find. Parents get contradictory folklore, apps that are glorified tally counters, and methods that quietly run on pressure and shame — which pediatric guidance consistently says backfires.
Potty Coach is a coach, not a tracker: log what happened in two taps, and the app tells you what to do next, what to say out loud, and why it works — adapted to your child's actual pattern, in the moment, with no network required. The product's one absolute constraint: zero shame language, ever, about the child or the parent.
Everything below runs on-device from pure rule engines — the app works in an airport bathroom with no signal. AI is an optional layer at the edge, not a dependency.
Two-tap logging on a canonical event vocabulary
Nine event types — from pee and accident through sit-attempt, refusal, and public success — write to local SQLite instantly. The vocabulary is the schema's spine: every engine downstream reads the same nine words.
▸ offline SQLite · 6 tables · 9-event canonical vocabulary · guarded ALTER migrations
Pattern detection
A pure-function analyzer turns raw logs into the flags that matter: resistance level, holding risk, accident trend, initiation trend, outing mode. No cloud, no model — deterministic rules a parent could audit.
▸ pattern-detector.ts · resistance / holding / trends computed on-device
Situation coaching
Eight high-stress situations — refusing to sit, holding too long, accident just happened, poop hesitation, public bathroom, about to leave — each with what to do, what to say (actual scripts), and why it works, adapted by the detected patterns and program day.
▸ 8 situations · scripts + rationale · adaptation flags from pattern engine
The 14-day program
A day-by-day plan with a cursor that knows when to hold steady: maintenance days are suggested when the pattern says consolidate, not advance. Day boundaries are calendar-based deliberately, so a nap through midnight or a DST shift never skips a day.
▸ program-engine.ts · maintenance-day logic · DST-safe calendar-day math
Moment-anchored reminders
Reminders anchor to the family's real moments — wake, before meals, before leaving, after returning, bath, bed — not arbitrary intervals. When resistance runs high, pre-meal prompts auto-suppress: nagging a resistant kid is the anti-pattern.
▸ 6 moment anchors · midnight-wrap-safe scheduling · resistance-aware suppression
Progress, badges & the Caregiver Brief
Streaks, a sticker chart, and a badge engine mark real milestones. The Caregiver Brief is the sleeper feature: a shareable one-pager that briefs grandma or daycare on the plan — including an explicit 'please avoid saying' list, so the zero-shame rule travels with the child.
▸ badge-engine over full log history · shareable brief with tone guardrails
Ask Coach — AI with hard privacy rails
An optional Claude-powered chat for the questions the rule engines don't cover. The child's name never leaves the device; message content is never stored; device and IP identifiers are hashed; usage is capped server-side and fails closed. It answers in the app's language.
▸ Claude Haiku via Supabase Edge Function · 30 msgs/day/device · SHA-256'd identifiers · no message storage
Three languages with enforced parity
English, Spanish, and Brazilian Portuguese across every script and screen — 3,370 lines of localized coaching content. A build-time check diffs every translation key against the English bundle, so an incomplete locale fails the build instead of failing a parent.
▸ custom i18n · en / es-MX / pt-BR · check:i18n parity gate · device-locale auto-detect
Asset pending
{{TODO: Today tab — program card + next action + quick log}}
Asset pending
{{TODO: Situation coaching screen (what to do / what to say)}}
Asset pending
{{TODO: Ask Coach chat with a real (anonymized) exchange}}
Asset pending
{{TODO: Caregiver Brief share sheet incl. 'avoid saying' list}}
Rules on-device, AI at the edge, in that order
The coaching engines are pure TypeScript functions over local data — deterministic, auditable, and functional with zero connectivity. Claude handles only the open-ended questions, through an edge function the app can gracefully live without. Most 'AI apps' invert this and break in a basement.
Zero-shame as an enforced constraint, not a value statement
The tone rule is engineered in three places: every locale's scripts are written to it, the Caregiver Brief ships an explicit avoid-saying list to other adults, and the LLM system prompt hard-bans shame patterns ('big kid', 'too old for', comparisons). {{TODO: commit the stashed 76-case engine test suite — it includes a regression test that scans every situation/day combination for shame language}}
Privacy designed for the App Store label, not retrofitted
The chat context schema structurally cannot carry the child's name; identifiers are hashed before storage; message content is never persisted. The privacy label was designed first and the architecture built to earn it.
Monetization staged behind a single flag
ALL_FEATURES_FREE=true ships v1 with RevenueCat never even configured — cleaner privacy label, no purchase surface to review-reject. The full Pro gate (paywall components, entitlement store, restore flow) is built and tested behind the flag, so turning revenue on is a config change plus a resubmit, not a project.
Translation completeness fails the build, not the user
A parity check flattens every key path in the English bundle and diffs es-MX and pt-BR against it — a missing key is a build error. Runtime still deep-merges over English as a belt-and-suspenders fallback.
- 5
- on-device rule engines (720 LOC, pure functions)
- 8
- coached situations with scripts
- 3
- languages — en / es-MX / pt-BR
- 3,370
- lines of localized coaching content
- 9
- canonical event types
- ~12K
- lines of TypeScript
- 30/day
- server-enforced Ask Coach cap per device
- {{TODO: post-launch downloads / ratings}}
- App Store traction
- Execute the submission runbook: Apple org enrollment, App Store Connect setup, TestFlight ship-gate, review submission
- Redeploy the Ask Coach edge function so chat replies follow the app language (command staged in the runbook)
- Post-launch: flip the Pro flag once reviews establish rank — paywall, IAP, and restore flow are already built