Case study · In development — live preview

ZzzStake
Put real money on your own sleep goal — miss it, and you forfeit the stake.

ZzzStake applies the commitment-device mechanic behind stickK and Beeminder to sleep: put money on a sleep goal you set yourself, and missing it costs you the stake.
The problem
Sleep trackers produce a score every morning and no consequence for ignoring it. Loss aversion is one of the most reliable levers in behavioral economics, and stickK and Beeminder already use it for habits. ZzzStake points the same mechanic at sleep.
How it works
You pick a goal — a sleep score, a consistent wake-up time, falling asleep by a set time, or hours slept — plus a window of nights, a stake, and how many emergency skips you want. Sleep data comes in from Apple Health, and a daily job settles every stake whose window has closed.
Meet the goal on every night except your skips and you keep your stake; miss it and the stake is forfeited. There's deliberately no upside beyond getting your own money back.
Engineering decisions
No real money until the gates close
The app runs as a live preview: stakes, scores, and outcomes are tracked end to end, and every forfeit is written to a ledger with no payment attached. Payment processing stays off until payment-provider approval and legal review are complete, because a bug in resolution would otherwise take someone's money.
Its own score, not Apple's
Apple's Sleep Score isn't available through HealthKit, so ZzzStake computes its own from raw sleep stages, weighting duration, consistency, and interruptions 50/30/20.
The published rules can't drift from the engine
The public FAQ's worked examples are computed by the real scoring functions, and tests pin the wording — if the formula changes, the explanation changes with it or the build fails.
Settles on outcomes, per goal type
Each goal type has its own pass/fail predicate, and the type system refuses to compile if a goal type is added without one.
Client-agnostic ingestion
Sleep data arrives through one authenticated endpoint that accepts raw samples from a health-export app, alongside a bulk importer for Apple Health exports. Real data flows without waiting on a native iOS build.
Dates are the hardest part
A night is dated by the morning you woke up, and all calendar math goes through one local-date module. An earlier UTC shortcut shifted evening stakes a night forward and closed cancellation windows hours early. The test suite is pinned to UTC with a guard test, so timezone bugs can't hide on a dev machine.
Recoverable writes without transactions
The serverless Postgres driver has no transaction support, so resolution is ordered: update the stake, then write the ledger, then send email last on a best-effort basis. A failure at any step leaves a state the next run can recover from.
Stack
- Framework
- Next.js 16 (App Router), React 19, TypeScript
- UI
- Tailwind CSS, shadcn/ui
- Database
- Neon Postgres, Drizzle ORM
- Auth
- bcrypt + JWT cookies, Google sign-in
- Validation
- Zod
- Resend
- Scheduled jobs
- Vercel Cron (daily resolution)
- Testing
- Vitest