The problem
Habit trackers exist everywhere, but nothing served Muslim daily worship well: counting zikr, logging the five daily prayers, tracking voluntary fasts against actual Islamic calendar rules, and building a Quran reading habit — in one place, with real analytics.
Key features
- Zikr counter — local-first tap counting with debounced batch sync, lifetime totals, daily goals
- Salat tracker — five daily prayers with status, location, and per-day history
- Prayer times — computed fully client-side from device location, no API dependency
- Fasting tracker encoding real fiqh: prohibited days (both Eids, Tashriq) blocked in the UI, disliked patterns warned, every rule linked to its source hadith with exact reference numbers
- Quran habit — daily pages goal, khatm (completion) progress bar, reading streaks
- Streaks with grace days — one missed day survives if the next is completed; backfill reconnects broken streaks
- Per-habit analytics dashboards with configurable date ranges
- 19-test backend suite (Jest + mongodb-memory-server)
Challenges
Timezones done right. A "day" for a user in Dhaka is not a UTC day. Daily buckets are anchored so the bucket's UTC date always equals the user's local date, and for prayer/fasting logs the client's local civil date is authoritative — the server clock never decides what "today" means. Daily resets happen at local midnight with zero configuration.
Write-heavy counters without lost updates. Zikr counting is a hot path — taps are counted locally first, then flushed in debounced batches. Server-side writes are atomic MongoDB operations ($inc, $addToSet), never read-modify-save, so concurrent batches can't lose counts.
No cron on free tiers. Streaks that should expire are evaluated lazily on read — the same result as a scheduled job, with zero infrastructure and nothing to monitor.
Domain correctness. Encoding fasting rules meant researching primary sources and linking each rule to its hadith reference — the app is only useful if the fiqh is right.
What I learned
- Client-authoritative time is the only sane model for habit apps with global users
- Atomic write patterns (
$incover read-modify-save) as the default for any counter under concurrency - Free-tier architecture is a real constraint discipline: lazy evaluation replaces cron, cold starts shape UX decisions