Skip to content
Terrero Labs

MindMap

Longitudinal behavioral health tracking: mood, sleep, stress, symptoms, and routines as structured time-series data.

Active developmentLive web app · pre-launch
Division
HeartWire
Role
Founder · design and development
Timeline
2025 – present

Turns repeated daily check-ins into a consistent multi-variable record, so questions like “does poor sleep precede my low-mood days, or follow them?” have data behind them instead of recall.

  • Next.js 15
  • TypeScript
  • Supabase (Auth · Postgres · RLS)
  • Recharts
  • Python (offline ML)
  • Vercel

01Problem / user need

Mental-health and chronic-condition self-tracking is usually either unstructured (a paper journal, a notes app) or locked inside consumer apps that reduce mood to one emoji per day. Neither produces data you can analyse.

Answering “does poor sleep precede my low-mood days, or follow them?” needs timestamped, multi-variable, longitudinal records under a consistent schema. Free-text journaling doesn’t produce that, and consumer apps don’t export it. MindMap exists to produce that record.

02Requirements

#RequirementAcceptance criterionStatus
R1Daily entry captureFull check-in completes in a bounded time, median over real sessionsNot yet measured
R2Data durabilityA day’s check-in is atomic: no half-written days; re-submit overwrites, never duplicatesDesigned in (single upsert RPC); not yet load-tested
R3Auth isolationUser A cannot read or mutate user B’s rows through any query pathSQL test suite written; run result not yet published
R4Cross-device syncEntry written on one device is visible on anotherNot yet measured
R5Analytics latency90-day dashboard renders within a p95 budgetNot yet measured

PendingThresholds are deliberately left blank until each criterion has a committed measurement. No numbers are published ahead of the test that produces them.

03Architecture

Solid lines are built. The ML layer is decoupled: it shares only the database.

04Design decisions

Single RPC for the daily check-in

Chosen
One Postgres function, upsert_mindmap_entry(jsonb), called from the check-in page.
Alternative
Separate client-side inserts per metric.
Tradeoff
The RPC makes a day atomic and idempotent — a partial submit cannot leave a half-written day, and a re-submit overwrites rather than duplicates. Cost: the JSON contract is untyped at the database boundary, so client/function drift fails at runtime instead of at build time.

Authorization in the database (Supabase Auth + RLS)

Chosen
Row-level security policies on every user table.
Alternative
A custom session and authorization layer in application code.
Tradeoff
A compromised client holding a valid anon key still cannot read another user’s rows. Cost: RLS policies become load-bearing security code and have to be tested like code — hence the isolation test suite.

Application-layer envelope encryption for journal text

Chosen
A random 256-bit data key per user, wrapped by a master key held only in server environment; journal bodies encrypted with AES-256-GCM. Rotated keys are kept so old entries still decrypt.
Alternative
Rely on the hosting platform’s disk-level encryption at rest.
Tradeoff
Platform encryption protects disks, not rows — anyone with database access reads plaintext. Envelope encryption narrows that to holders of the master key. Cost: key management, a backfill path for existing rows, and journal text that can no longer be searched in SQL.

Rules first, ML as an assistive layer that can abstain

Chosen
A deterministic rule baseline, plus a calibrated model that returns “not enough data yet” instead of a number when evidence is thin.
Alternative
A learned model as the primary engine.
Tradeoff
Rules give output on day one and every result traces to its rule. The model has to beat that baseline to earn a place. Cost: rules only find relationships someone thought to encode.

PWA on Vercel rather than native mobile

Chosen
One Next.js codebase, deployed continuously.
Tradeoff
No app-store review and instant deploys. Cost: no background sensor access and weaker iOS notification reliability — which matters for a habit-dependent product.

4.5Scope & role

Independent project under Terrero Labs. I designed the schema, wrote the application, RLS policies, encryption helpers, and the ML package, and run the deployment.

05Implementation

  • Software: Next.js 15 App Router, TypeScript, Supabase JS client, Recharts, deployed on Vercel.
  • Auth: sign-up, sign-in, sign-out, and an email-confirmation route handler.
  • Database: versioned SQL migrations for the schema, RLS policies, and function grants.
  • Encryption: server-only AES-256-GCM helpers wired into the journal write paths behind a configuration flag, with a backfill script for existing rows.
  • ML (offline, Python): feature pipeline with lags and rolling windows, rule baseline, per-outcome calibrated logistic regression, an abstention contract, and an output gate that blocks diagnostic phrasing before any text reaches the app.
  • CI on every push: TypeScript typecheck, engine unit tests, and the ML package’s pytest, ruff, and mypy.
  • Hardware: none. MindMap has no device integration.

06Verification

  • Automated checks run in CI on every push: typecheck, unit tests for the insight, correlation, prediction, crisis-detection and encryption modules, and ML tests.
  • Playwright end-to-end specs cover auth routes, authenticated pages, and legal pages.
  • The ML layer has been evaluated leave-one-user-out on synthetic data only, with personas whose ground-truth effects are known. Its model card states that next-day migraine prediction is not reliably better than chance.

PendingNot yet published: the cross-tenant isolation result (the SQL suite exists; the run output isn’t committed), the end-to-end auth run report, and any evaluation on real user data.

07Failures / iterations

  • A missing NEXT_PUBLIC_APP_URL in the production environment sent email-confirmation redirects to the wrong origin. Lesson: variables that differ between local and production are their own failure class; .env.example should be a checked-in contract.
  • A July 2026 self-audit of the codebase found /api/v1 endpoints returning hardcoded sample data behind header-presence “auth”, notification packages installed but never wired, and a wearables screen with no ingestion source. I wrote these up in the repo rather than leave them implied by the UI.
  • Framework debt: Next.js middleware is deprecated in favour of a proxy file in Next 16.

08Limitations

  • Not a medical device. Makes no diagnostic, therapeutic, or clinical claim and has not been evaluated under any FDA pathway.
  • All inputs are self-reported. No physiological ground truth or sensor data.
  • Surfaced patterns are correlational and descriptive. The app does not establish causation or control for confounders.
  • Journal encryption is implemented in code; I haven’t independently confirmed here that it is enabled in the production environment.
  • The ML layer has no real-data validation. Synthetic-data results show the pipeline works, not that it predicts anything for real users.
  • No external security audit or penetration test has been done.