-
the goal is to build a simple habit tracker using a github contribution-graph-like heatmap to be able to track consistency across habits
-
user must be authed to view habits
-
show all habits on one screen, upto 10 at a time, then implement pagination
-
in addition to habits, also display streak for each habit
-
however, not all habits need to be done daily, and this shouldn't affect the streak score, so there need to be types of habits (can start with daily, once a week, weekdays only, weekends only) and skipping non-required days shouldn't affect the streak.
-
habits should be re-orderable, and configurable: clicking on the settings button for a habit should flip the habit card and reveal settings
-
settings can include habit type (daily, etc) and also fun things like theme color maybe
-
at a later stage, can add a kind of dashboard view to see all habits / stats at a glance
-
new idea: connect with notion: each green square represents an entry on a notion db that is a journal entry about how I fulfulled the habit that day
- Stay as close to github's implementation as possible
- show months, no days
- show last 365 days only.
- initial idea was to store completions as a binary string (eg: "01011110101111") as a column in the habit table
- while this will probably work forever for my scale, I want to build something ready for large scale anyway.
Production Ready Approach:
- A dedicated table for
Habit_Completions - Stores completion events in the form "User X completed Habit Y on Date Z", ensuring that there can only be one entry for a habit on a day by the user.
- Retrieve completions of a user as "Get all completion dates (limited to the last 365 days) by User X for Habit Y"
- Not sure yet how I will parse this data and then feed it into the heatmap, probably with a map like ({"2026-02-04": true})
- moving streaks to next iteration
- simple implementation idea to add streaks with undo: https://www.notion.so/akashamba/Habit-Tracker-app-2f75aa83c5cb8044a2e9d71af69d1a98?source=copy_link#2fd5aa83c5cb805d9b8df02963a85e0f
- nextjs
- taiwlind css
- maybe shadcn components
- likely will use a pre built component for the contribution graph
- trpc
- postgres db
- auth using google sso
- hosted on vercel
- Condensed view
- Batch operations
- Undo longer than 30s (maybe only current day)
- X times a week Frequency is an essential
- show month and day info like github
- “Streak freeze” token you can spend once per week
- haptics and animations for all interactions as appropriate. use https://haptics.lochie.me/ for haptics
Iteration 1
- view habits
- Habit actions: create and delete habits (with confirmation modals)
- make habit entries
Iteration 1.5
- encrypt access tokens
- optimize indexes
- reorder habits
- squares for current day only show up on current the day, like github
Iteration 2:
- Habit settings menu (with card flipping animation)
- habit types/frequency
- theme colors
- Reorder habits
- Archive habits
- Batch features (batch complete, delete)
- Timezone support for using across multiple regions
Iteration 3:
- local first + offline access
- email reminders
Iteration 4:
- Social features: add friends, see their streaks, leaderboards, etc
- connect with notion to make journal entries about each completion
- set up db, auth, hosting
- deploy pipelines
- finalize a UI, schema, and api endpoints with data signature
- set up rough trpc router and seed db with fake data
- develop UI
User ( cretaed by better-auth already )
Habit ( id: uuid, primary_key, user_id: uuid, foreign_key, name: string, created_at: timestamp, updated_at: timestamp, )
Habit_Completions ( id: uuid, primary_key, habit_id: uuid, foreign_key, completed_at: timestamp ) Index: UNIQUE(habit_id, date)
-
GET: Fetch all habits (with completions)
-
POST: Create a new habit
-
- Params: habit_name
-
DELETE: Delete a habit
-
- Params: habit_id
-
POST: mark habit as complete
-
- Params: habit_id
-
POST: undo completion
-
- Params: habit_id
-
PATCH: update habit (rename now, later archive/unarchive, etc)
-
- Params: habit_id, new_name
- set up db for habits project on neon and deploy to vercel (30 mins)
- set up auth for habits project (15 mins)
- try to make better auth sign in on server as implemented in create-t3-app template
- finalize UI on figma
- make rough sketch of schema
- make rough sketch of api endpoints
- set up trpc router
- set up a seed script with fake data in db
- scaffold UI (everything except heatmap component)
- make ui for heatmap component
- parse completion data to render it in the heatmap ui
- style everything with css
- add event handlers for create, delete, complete
- add shadcn for dialogs, dropdowns, user avatars, etc
- add rename habits feature
- add undo completion
- completion graph shows the beginning by default, when I actually want it to show the end by default. can be fixed usings refs.
- make app pretty (loading spinners, align whole app width to sm and center, signed out page, etc)
- add logo to navbar
- streaks currently show only total count, add proper streak calculation
- refactor habit component
- timezones (new day appears at 8 pm EDT (12 am UTC))
- modal for delete
- optimistic update for create
- completion graph elements should not be selectable
- db push when there are tables already fails because of the sql expression column in the UNIQUE constraint of the habit_completions schema
- Temp solution: manually drop the index on neon and then push the new schema, which will automatically add the schema
- update longest_streak correctly when undoing a completion, or leave it as append only field
Store date in UTC, store timezone separately. Do all time calculations in UTC, convert for display only. FWIW Luxon is a great time/date library, used this in work for scheduling for an automated patching system.