Daily Quests
A gamified daily habit tracker for iOS inspired by World of Warcraft's quest system. Earn virtual currency, track streaks, unlock achievements, and redeem custom rewards.
Daily Quests
An iOS app that turns daily habits into a game. Instead of checking off a to-do list, you complete quests, earn Daily Dollars, and unlock achievements — all without a single third-party dependency.
The Idea
Traditional habit trackers feel like chores. I wanted something that actually made me want to open the app. World of Warcraft’s daily quest system was the inspiration — scheduled tasks that reset each day, rewarding consistency with currency you can spend on things you actually want.
How It Works
You create quests with scheduled times and weekday restrictions. When a quest’s time arrives, it moves from “Upcoming” to “Available” on your quest board. Complete it, earn Daily Dollars. Complete all your quests for the day, your streak increments and confetti rains down.
The Daily Dollars aren’t just for show — you build a personal reward shop with things like “Movie night” or “Takeout dinner” and set prices. It’s a self-reinforcing loop: do the boring stuff, earn the fun stuff.
Architecture Highlights
No Timers, No Background Tasks
Quest availability is computed at read time. There’s no midnight cron job resetting state. When the calendar date changes, old completion records naturally become “yesterday’s” — every quest is available again without mutating a single row. This eliminates an entire class of bugs around timezone edge cases and missed background refreshes.
Cross-Process Data Sync
The app shares data with its home screen widgets through App Groups and a shared ModelContainer. Interactive widgets let you complete quests without opening the app, which means two processes can write to the same database simultaneously. A QuestCompletionService with file-based locks coordinates writes, and lightweight QuestSnapshot structs (not SwiftData models) prevent serialization issues across process boundaries.
Intelligent Streak Tracking
The streak system respects your schedule. If you have no quests on Sunday, your streak doesn’t break on Monday. On app launch, StreakTracker walks backward through your calendar to find the most recent “scheduled day” and validates that all quests were completed. Miss a day that had active quests? Streak resets. Skip a day with nothing scheduled? You’re fine.
Tech Stack
- UI: SwiftUI with custom theme (parchment backgrounds, gold accents)
- Data: SwiftData with schema migrations (v4, backward-compatible backups)
- Widgets: WidgetKit + App Intents for interactive home screen completion
- Notifications: UserNotifications for daily reminders and per-quest alerts
- Testing: 6 test suites — unit tests for core logic, UI regression tests
- Dependencies: Zero. Built entirely with Apple first-party frameworks.
Features at a Glance
- Quest Board with Available / Upcoming / Completed sections
- Daily Dollars virtual currency earned on quest completion
- Reward Shop with custom rewards and redemption history
- Streak Tracking with milestone achievements (7, 14, 30, 60, 100, 365 days)
- 90-Day Completion Calendar heatmap
- Interactive Widgets (small + medium) with one-tap completion
- Bundled Quest Packs — Morning Routine, Fitness, Study, Self-Care
- Full JSON Backup/Import with backward-compatible schema versioning
What I Learned
SwiftData’s cross-process story is still rough. Getting the app and widget extension to share a ModelContainer reliably required careful choreography — App Groups for the shared container, value-type snapshots to avoid serialization crashes, and file locks for write coordination. The Apple documentation barely covers this, so most of it was figured out through experimentation.
The “no timers” architecture was the best decision. Every feature that touches quest state — completion, streaks, widgets, notifications — benefits from the same simple rule: read the date, compute the state. No sync bugs, no stale caches, no “why did my quest not reset” support tickets.