Background
Most productivity tools optimize for task lists. I wanted something that captures intent vs. reality across days: what you planned in the morning vs. what actually happened by evening. That gap is where recurring blockers and energy patterns show up, but you can't see it in a single entry.
What I built
- A two-check-in daily ritual (morning plan, evening reflection), not a task manager
- An AI layer that reads ~2 weeks of history and surfaces patterns you'd miss on your own
- Weekly digests with shareable links, plus a dashboard for streaks, follow-through, and mood
Concept to deployed product in a focused weekend sprint. The bet was that a tight ritual plus honest reflection beats another productivity dashboard.
Architecture
React SPA
X-Timezone · Bearer JWT
Rails 8.1 API
PostgreSQL
Users, check-ins, digests
OpenAI
Nudge, summary, digest
Public Share
Token-based, no auth
Stack choices
- Rails API + React SPA, fully decoupled so I could move fast on product without fighting a monolith
- Timezone on every request so “today” is always the user's local date, not the server's
- AI through one service class over raw HTTP, with no SDK or job queue and quiet degradation when OpenAI is unavailable
Morning / Evening Pairs
The product question was: what's the smallest unit of accountability that still captures a full day? I landed on a paired ritual, not open-ended journaling and not checkbox tasks.
Everything in the product builds on one comparison: what you planned vs. what happened. That's why check-ins live in a single table with a morning/evening enum, not separate models or a generic journal entry. A composite unique index enforces one of each per day, and conditional validations mean mornings ask for a plan while evenings ask for a reflection.
The metric I actually track is follow-through: how often a morning check-in gets an evening reflection on the same date. When you set an intention, did you close the loop?
Timezone was the annoying edge case. If the server is UTC and you're in Tokyo, “today” shifts. I sync IANA timezone on every request and compute dates in the user's zone, not the server's.
AI Guardrails
There are three AI touchpoints: a one-sentence nudge after check-in, a daily summary when both halves of the day exist, and a weekly digest. The nudge was the hardest to get right. Early versions just echoed what you'd written or cheered you on, which was useless.
What actually worked
- Constrain what the model shouldn't do before telling it what to do: no echoing the check-in, no generic advice, no cheerleading
- Wait for at least 3 recent entries before activating, since pattern-matching on one data point isn't useful
- Fail silently when OpenAI errors or history is too thin, showing nothing instead of a broken or generic nudge
Weekly digests split narrative from math. The model writes wins, patterns, and blocker analysis, but average energy and completion rate come from raw check-in data on the server. I didn't want the LLM deciding what someone's completion rate is.
Sharing is per-digest with a public link. Wins and patterns can go out; blocker details stay private.
Ritual, Not a Form
For something you open twice a day, friction kills retention faster than missing features. I treated the UI as part of the product bet, not decoration.
Check-ins use 3D card flips: prompt on the front, form on the back. Signed-out users see tilted peek cards; signed-in users get full panels with a shared layout animation between the two states.
Mood is raindrop/flame/sun glyphs instead of a 1–10 slider. Faster to answer, easier to scan when you scroll back through history. History runs horizontally with today on the left, one API call for 90 days instead of paginating.
What surprised me
- WebGL shaders, physics-based card tilts, and greeting animations turned out load-bearing, turning a daily obligation into something you actually want to open
- Dashboard stats from two aggregate queries instead of per-day fetches, fast enough to feel instant on open
Results
Concept to deployed product in a focused weekend. The daily ritual takes under a minute, and the AI context window covers two weeks of history before it starts surfacing patterns.
< 1 min
Daily check-in time
14 days
AI context window
36 hrs
Concept to deploy
What's Next
Once you're checking in daily it sticks, but nothing brings you back when you forget.
- Push notifications for morning and evening reminders
- PWA for home screen install on a daily-use tool
