CBT-I Coach
An installable PWA that self-administers the CBT-I protocol for middle-of-the-night insomnia.



The Problem
Sleep-maintenance insomnia — waking at 3am and not getting back down — is treatable with CBT-I, but the standard of care is weeks of clinician-guided sleep restriction most people never access. The math behind it (rolling sleep-efficiency windows, when to trim or extend time in bed, when a night doesn't count) is exactly the kind of protocol a phone can run, if the clinical logic is faithful to the source.
What I Built
A mobile-first PWA on Next.js 16 + Postgres (Neon) + Drizzle. The heart of it is a pure, framework-free clinical engine — no React, DOM, or DB imports — that computes sleep efficiency, prescribes the time-in-bed window, and titrates it on a rolling average of valid nights, all unit-tested against the Spielman/UPenn protocol. A nightly diary drives a bed → awake → up stamp cycle; a Progress view charts the window journey and efficiency since baseline. Per-local-time reminders and titration nudges run off an external cron polling a tick route, delivered through a hand-rolled VAPID / RFC-8291 Web Push implementation in Node stdlib.
Notable
The clinical rules are load-bearing and deliberately conservative: a five-hour floor that time in bed never drops below, and a stabilization lockout that holds a window until enough valid (non-atypical) nights have actually accrued since the last change — a valid-nights count, not a calendar timer, so a change never fires on a window still contaminated by pre-change nights. Fragile UI logic (which night-cycle button to show, and when) was pulled out of the component into a pure tested helper after it caused three rounds of "right button, wrong time" bugs — the engine decides, the component only renders.
Stack
Status
Live at cbt-i-coach.vercel.app.