Most habit trackers are spreadsheets with extra guilt. I wanted one that felt like playing a game, so I built one that borrows its mechanics honestly — including the parts that are annoying.
The premise
Habits are quests. Completing one grants XP. XP raises stats. Stats gate the quests you're allowed to take.
The deliberate cruelty: stats decay every day you don't act. Your Strength doesn't sit there politely at 40. It's 39 tomorrow. 37 by the weekend. This is copied directly from RPG mechanics, and it turns out to be the single most effective feature. The decay is the actual product; the quests are just the interface.
Stack
- React + TypeScript — nothing exotic
- SQLite via a thin typed layer. I resisted an ORM and wrote about 200 lines of query helpers instead, which was the right call for something this small
- Local-first. The whole database is one file. No account, no sync, no telemetry
- Markdown quest files on disk, so a quest is just a file with frontmatter
The interesting technical bit
Quest definitions are data, but quests have prerequisites and rewards, which makes them a graph. I needed transitive prerequisite resolution without pulling in a graph library, and the whole thing is a fixed-point iteration:
function isUnlocked(quest: Quest, completed: Set<string>): boolean {
const seen = new Set<string>()
let frontier = quest.requires ?? []
while (frontier.length > 0) {
const next: string[] = []
for (const id of frontier) {
if (seen.has(id)) continue
seen.add(id)
if (!completed.has(id)) return false // unresolved requirement
const dep = questIndex.get(id)
if (dep?.requires) next.push(...dep.requires)
}
frontier = next
}
return true
}BFS over requirement edges, memoised per quest per session. Forty quests, sub-millisecond.
Status
Still in progress, and honestly still fun, which is the real test. The parts left to build are a stats page with actual charts and an export button that produces a shareable image.
What I learned
If your productivity tool doesn't have a win condition, it's a chore list. The entire difference between this app and a plain checklist is that it tells you, in specific terms, what you gained and what you're about to lose.
Games solved motivation decades ago. We just stopped taking notes.