← All Projects
Drink Water

Drink Water

Cross-platform mobile app to track daily water intake with persistent history, configurable reminders, and automatic midnight reset

react-native
expo
typescript
sqlite
notifications
context-api
mobile
background-tasks
animation
theme-system
asyncstorage
app-hero

Problem

Simple hydration trackers either lost the counter on app close, required an account for reminders, or reset at the wrong time. There was no lightweight offline-first option that combined persistent history, a reliable midnight auto-reset, and notifications that actually fired through Android's battery optimization.

Stack Decisions

AsyncStorage for the counter, SQLite for history

The daily counter only needs a single integer and must be synchronous on read. AsyncStorage is the right fit. History needs date-grouped aggregation and per-entry deletion — that's a SQL query, not a key-value lookup.

Expo Background Fetch for midnight reset

The reset had to fire even when the app was backgrounded or closed. Background Fetch is the only Expo primitive that gets periodic CPU time without a persistent foreground service, making it the right trade-off for a low-frequency task.

Android MAX-importance notification channel

Hydration reminders compete with hundreds of other app notifications. A MAX-importance channel with a custom vibration pattern ensured the reminder broke through Do Not Disturb and appeared as a heads-up notification rather than a silent badge.

Challenges

01

Reliable midnight reset across battery optimization

Android aggressively kills background tasks on low-power devices. Registering the Background Fetch task with a minimum interval and a fallback reset on app foreground covered the cases where the OS skipped the background wake-up.

02

Notification schedule surviving reinstalls

Scheduled notifications are cleared on uninstall. The app re-registers the full reminder schedule on every cold start if no active triggers are found, so reinstalls don't silently disable reminders without the user noticing.

03

Duplicate history entries on backgrounding

If the app was foregrounded multiple times in the same day, the history write could fire more than once for the same date. An upsert pattern — insert or update where date = today — made the write idempotent regardless of how many times the app lifecycle triggered it.

Outcome

A dependency-light mobile app that reliably tracks daily intake with no backend, no login, and configurable reminders that fire on schedule. The Background Fetch midnight reset worked correctly on all tested Android versions including aggressive battery-savers like MIUI, which was the main technical risk for the feature.