A visual, mobile-first habit tracker PWA built with Next.js, Tailwind and the Google Sheets API. This is the real habit system I use every day - synced to the same Google Sheet I track my habits in.
The app renders a month-by-month calendar UI, hydrates from my Sheet on load, and updates the Sheet instantly when I mark habits complete.
Google Sheet ←→ Sheets API ←→ Next.js API Routes ←→ React Frontend
The frontend calls GET /api/habit on mount, which:
- Authenticates with Google via a service account
- Reads the sheet and returns completed dates for all habits (Software, Music, Gym)
- Groups entries by habit using a config-driven column mapping
Tapping an uncompleted date:
- Instantly updates the UI (optimistic update)
- Triggers haptic feedback (Vibration API on Android, hidden
<input switch>workaround on iOS 18+) - Fires an async
POST /api/habitto write the value into the correct sheet cell
Tapping a completed date opens a draggable bottom sheet where you can:
- Log time spent (minutes or hours)
- Add notes
- Remove the entry
The bottom sheet uses velocity-based gesture detection for natural swipe-to-dismiss.
Habits are driven by a single HABIT_CONFIG object that maps each habit to its sheet columns. Switching between habits is done via arrow navigation, and adding a new habit requires only a config change.
- PIN-based authentication with rate limiting and secure HTTP-only cookies
- All secrets (private key, sheet ID) stored in environment variables
- Frontend: Next.js 16, React 19, TypeScript, Tailwind CSS
- Backend: Next.js API Routes, Google Sheets API
- Deployment: Vercel with automatic CI/CD from GitHub