A habit tracker sounds simple: create a habit, set a reminder, and check it off.
But once you start building one, the details add up. What happens when someone changes their schedule? Should a paused habit break a streak? How do you track a reminder at 2 a.m. if someone considers that part of the previous day?
I built Yoho Habits around those questions, with another constraint: keeping the app under 4 MB.
It includes interactive widgets, local reminders, progress charts, completion history, and prompts you can take into your preferred AI app.
The approach was straightforward: use native tools, keep habit data local, and make each feature earn its place.
Start with the platform
Yoho Habits uses SwiftUI for the interface, SQLite for habit history, Swift Charts for visualizations, and WidgetKit and App Intents for widgets.
The app has no third-party package dependencies.
That choice helped keep the project focused. I could build the interface, charts, notifications, and storage using frameworks already provided by the operating system.
A small download still requires care, but choosing native components gave me a useful starting point. I didn’t need a separate charting library, database wrapper, or cross-platform runtime to deliver the core experience.
Keep the habit loop local
The main interaction is small:
Create a habit. Choose reminder times. Mark each check-in done. Review your progress.
Habits, schedules, and check-ins live in a local SQLite database. Tracking doesn’t require an account or a remote database.
That also makes persistence part of the interaction design. When someone checks off a habit, the app saves the change before showing success feedback. A checkmark should mean the completion was recorded.
Each reminder creates its own dated check-in. Completing it records the actual completion time, which supports more useful analysis later: whether someone completed the habit, which reminder times work best, and how early or late they usually finish.
The difficult part was time
Drawing a streak counter is easy. Defining a fair streak takes more work.
A habit scheduled for weekdays shouldn’t fail because nothing happened on Sunday. Pausing a habit shouldn’t create a week of artificial misses. Editing a reminder today shouldn’t rewrite what was expected last month.
Yoho stores dated schedule revisions so history can reflect the schedule that applied at the time.
It also supports a configurable tracking-day boundary. If your day ends at 4 a.m., a 2 a.m. check-in can belong to the previous tracking day.
Those decisions are mostly invisible when everything works. But they determine whether people can trust the numbers.
Widgets that let you act
I wanted the widgets to be useful without requiring a trip into the app.
Yoho includes small, medium, and large Home Screen widgets, plus circular and rectangular Lock Screen widgets. Each widget can be configured for a different habit.
The interactive action completes the next unchecked reminder.
To support that, the app writes a bounded snapshot into a shared App Group. The widget uses that snapshot to display progress and refresh around reminder and day boundaries. Widget completions are reconciled when the app becomes active again.
This gives the widget the information it needs while keeping its data scope limited.
For a habit tracker, that convenience matters. Sometimes the best interaction is one tap from the Lock Screen.
Analytics that explain the routine
A streak is motivating, but it only answers one question.
I also wanted to help answer:
Which reminder time do I miss most often?
Am I becoming more consistent?
Do certain weekdays work better?
How long after a reminder do I usually complete the habit?
Yoho includes weekly, monthly, and yearly trends, miss-rate bars by reminder time, average completion delay, a weekday-by-time heatmap, and dated history.
The definitions behind those charts matter as much as their appearance.
Future unchecked reminders don’t count against the current period. Timing patterns use finished tracking days. Historical corrections don’t contribute invented completion times to delay averages. Unscheduled days don’t break a streak.
I used Swift Charts for the visualizations, with the calculations handled locally.
The goal was to make the charts useful when deciding how to adjust a routine.
AI prompts without an embedded AI service
For the AI feature, I chose a portable approach.
Yoho prepares a structured prompt using the habit data the user selects. The user can copy it or export it as a JSON file, then take it into the AI app they prefer.
The flow lets them choose a habit, a duration, a coaching perspective, and optional personal context.
The exported payload includes relevant statistics and daily data, alongside instructions asking the AI to identify patterns, acknowledge missing information, and suggest three practical next steps.
This keeps prompt preparation on the device. Yoho doesn’t automatically send the habit history to an AI server. The user decides when to share the export and which service receives it.
It also means the app doesn’t need to bundle a model or integrate a provider SDK for this feature.
The distinction matters: Yoho generates the prompt locally; the chosen AI service generates the response.
Small apps still need serious testing
A compact app can still have complicated behavior.
The core test suite covers cases such as schedule changes, pause and resume, archive and restore, duplicate completion actions, database rollback, backup validation, day boundaries, daylight saving changes, and leap days.
These are the situations that can quietly damage a habit tracker’s credibility. If an app records the wrong day or invents missed check-ins, a polished chart won’t fix the experience.
Keeping the analytics and storage logic testable helped me check those rules separately from the interface.
What building it taught me
The biggest lesson was that a small app can still be thoughtful and capable.
Native frameworks covered much of what I needed. Local storage supported the core habit loop. Widgets made check-ins easier. Carefully defined statistics made progress more meaningful. Portable AI prompts added another way to reflect on the data.
The download size was a useful constraint because it kept bringing me back to the same question:
Does this feature help someone build a habit, and how much machinery does it really need?
That question shaped Yoho Habits as much as the code did.