Problem
Long-distance couples run on asynchronous context: how she is actually doing, whether now is a good time to talk, what would genuinely help today. Cycle-tracking apps hold half of that context but are built for one user. The partner is either locked out or handed raw clinical data with no guidance, and most "share with your partner" features make her data the product and him the audience.
Users
Two people: one couple, in a long-distance relationship, with patchy connectivity (hostel wifi, metro commutes). That is the whole user base, by design.
The contract that shaped everything: she is a first-class user, not a subject. Her data is hers; sharing is per category, under her control, and revocable instantly. His experience is keyed on his own context (sleep, stress, energy), so the app tells him how to show up, not how to monitor.
Decision
Trade-offs
- Transparent scoring, no magic ML. Guidance ranking is a deterministic formula (feedback-weighted, recency-decayed) the code can explain. Predictions widen their confidence window when cycles vary, say "learning" under two cycles of data, and never claim fertility-planning precision.
- Offline is the normal case. Every write queues locally (Dexie/IndexedDB) with per-field merge, dead-lettered failures and idempotent replay, so "saved" means saved.
- Notifications pull you in, never spam. Discreet lock-screen text by default (never cycle details), quiet hours, a daily cap and per-kind dedupe, all enforced server-side.
- Column-level gating costs trust concentration. Row-level policies cannot gate columns, so column rules live in SECURITY DEFINER functions. Workable, but it concentrates trust in a handful of functions that deserve their own audit.
What shipped
The mock-up at the top of this page uses invented demo data, not a screenshot of the private deployment: Person A controls what Person B can see, and unshared categories never reach his view.
Three views share one engine. Her side: a quick daily check-in, a journal with per-entry sharing, a cycle dashboard and phase-aware suggestions. His side: a shorter check-in and guidance keyed on his own state, plus whatever she has opened via sharing dials. Us: side-by-side insights, an expectations exchange ("I can give / I need"), a weekly retro with appreciations, and scheduled partner messages.
The guidance engine drew from a 220-item content library at v0.1.0 (her/him/us × phase × mood band × stress band), later grown to 284. It filters by today's context, ranks by one-tap feedback (helped/meh/worse), enforces diversity against yesterday, and degrades honestly when a context cell is sparse. The cycle engine is pure, timezone-safe functions with an explicitly labelled ovulation estimate.
Open Book mode (full mutual visibility) exists only as a couple-level setting both must enable and either can revoke instantly.
Milestones M0 to M8 (onboarding, check-ins, journal, cycle engine, guidance, dashboards, notifications, weekly plans, couple layer) landed between the first commit on 3 Aug 2026 and the v0.1.0 tag on 12 Aug 2026.
Under the hoodArchitecture and implementation
React 19 + TypeScript + Tailwind v4 PWA on Vercel's free tier; Supabase (Postgres, email-OTP auth, Edge Functions) on its free tier; a transactional email provider's free tier for OTP mail. A pg_cron-scheduled Edge Function dispatches six nudge types through Web Push. No third-party analytics, trackers, CDNs or fonts.
The RLS matrix runs in rolled-back transactions against the hosted database, checking owner, partner-shared, partner-private, other-couple and anonymous access for every table, two-sided Open Book consent with instant revocation, no cross-couple leakage, and no back doors through helper functions.
Validation
- 575 RLS policy checks, 575 passing, recorded in the project roadmap on 13 Aug 2026; the matrix grew milestone by milestone from 95.
- A real leak found before release. A pre-release privacy review found plans indirectly revealing categories that had not been shared; the policy matrix is what made that contract checkable.
- 1,940 unit test assertions across 121 test files (self-recorded at the time of writing; the repository has since grown), plus Playwright visual regression at 320px and 412px in both themes.
- 220 guidance items at v0.1.0, with tests asserting dietary, situational and medical-claim constraints hold across the library.
- $0 a month hosting on free tiers (self-recorded).
Limits and next
- Deployed for two private users; not a public product. There is no public link, and its data is nobody else's business. That also means there are no usage metrics.
- Next: client-side encryption for private journal entries, so even the database operator cannot read what she marked private.
- Audit the definer functions. The SECURITY DEFINER functions that carry column-level rules deserve their own review ceremony.
Credits
Solo build: product, design and engineering. The image on this page is an illustrative mock-up with invented data; the real deployment stays private. How the sharing rules became a test suite is written up in Turning a privacy contract into a regression suite.

