All projects

7habits

The seven daily habits that matter most, one tap a day.

BusinessApp Store2026
View on the App Store

Problem

Most habit apps hand you a blank screen and ask you to invent your own habits. That is the hardest part, and it is where most people give up.

Solution

7habits removes that decision. It is built around seven daily habits that research links to a healthier life, prayer, gratitude, connection, exercise, hydration, sleep and nutrition. You do not design a system. You just tap once a day, and consistency turns into colour you can see.

What it is

A habit tracker for iPhone and web, built around seven fixed daily habits, so you track what matters instead of starting from nothing.

Design process

01

General research

I started from a simple idea. The habits that shape a healthier life are already known, prayer, gratitude, connection, exercise, hydration, sleep, and nutrition. The problem is not knowing them, it is keeping them.

02

Market validation

Most habit apps fail people by handing them a blank screen and asking them to design their own system. That is the hardest part, and it is where people quit. A fixed, ready made set of habits was the gap.

03

Ideation

I designed the app around those seven habits, one tap a day, with colour that deepens as your streak grows, so your consistency becomes something you can see.

04

Testing

I ran multi perspective audits of the app and the copy, tested purchases on the simulator and on TestFlight, and checked every flow with real screenshots.

05

Iteration

I fixed in batches from those audits and from real user reports, twenty one fixes in one pass, nine in another, and a full sweep that cleaned up the trial and pricing wording across the app, the site, and the store.

06

Build

I built the seven habit tracker, a stats dashboard with a heat map and streaks, milestone celebrations, an evening reminder, and the whole payment system on StoreKit with a monthly, yearly, and lifetime plan.

07

Test

Before launch I set up TestFlight groups, verified the purchase and restore paths, and made sure a paying user is never locked out by a transient or offline check.

08

Release

7habits is live on the App Store and on the web at 7habits.app, with all three plans approved.

Technical breakdown

TypeScriptReactViteCapacitor 7StoreKit 2ZustandTailwindFramer MotionAVAudioEngine

7habits is a React and TypeScript app built with Vite and Tailwind, wrapped for iPhone with Capacitor. It is local first, so all of your habit data lives on the device with no account and no backend. Two small native Swift plugins bridge into Apple, one for the purchases through StoreKit, and one for the sound. There is also a web version of the app at 7habits.app.

Architecture

A local-first web bundle wrapped in Capacitor, with two native plugins

The shipped iPhone app is a React and Vite bundle running inside Capacitor, with no server and no account, and all habit data held on the device through Zustand persisted to Capacitor Preferences. Only two jobs drop to native Swift, a StoreKit purchases plugin and an audio plugin, because those are the two things a web view genuinely cannot do well. Reaching for native only where the web layer actually fails keeps almost all of the app in one fast, portable codebase.

Platform gotcha

Owning the audio session the web view kept muting

The habit notes are synthesised in WebAudio, and iOS silenced them on the ring switch, because WebKit classes WebAudio inside a WKWebView as ambient audio and sets that category from its own process, out of my reach. So I wrote a native audio plugin with AVAudioEngine that claims the session as playback with mixWithOthers, while the web layer still decides the pitch and length of each note, so the sound is unchanged. When a web view fights you over a device capability, move only the capability to native and leave the logic in the web.

Payments

The purchase bug that was a missing plugin registration

On device, purchases did not work at all, and it was not the StoreKit code. The plugin was simply never registered with Capacitor, so the bridge did not exist. Registering it was the whole fix. On top of that I surfaced the real StoreKit error on the paywall instead of a generic failure, and retry product loading with a backoff. When a native bridge does nothing at all, suspect the wiring before the logic.

Payments

Reading entitlement so a paying user is never locked out

The app reads your entitlement silently from Transaction.currentEntitlements, with no AppStore.sync and no sign in prompt on launch, a lifetime purchase is never revoked, and a transient or offline check never removes access. Refunds and expiries re lock naturally, because they are simply absent from currentEntitlements. The rule is to fail open for a paying customer, a flaky network should never lock someone out of what they bought.

Payments

A trial that a clock change cannot reset

There is a short free preview after onboarding, then the paywall, and it is tracked by a last seen timestamp rather than a live countdown, so moving the device clock backward does not hand you a fresh trial. Any client side time gate has to assume the user can move the clock, so anchor it to a stamp you control, not to the wall clock.

App Review honesty

Removing a dead trial layer and dishonest copy

Apple rejected a build over prices shown in screenshots, and separately I found the app still carried no credit card and free trial wording that no longer matched the real, card required StoreKit trial, spread across the app, the landing page, and the store metadata. A five reviewer sweep deleted the dead app managed trial layer and aligned every word to what actually happens. Dishonest copy is not only a review risk, it is a promise your product then has to keep.

App Review

The Lifetime plan that could not ship alone

After the subscriptions were approved, the 99 dollar Lifetime, a non consumable, hit the rule that a first non consumable must be submitted on a version, and could not ship on its own. I carried it on a new version 1.0.1 submitted together, then released all three plans. Some App Store rules are about which items ride on which version, and you tend to learn them only by hitting them.

Notifications

Stopping a trial reminder from reaching people with no trial

A day twenty nine, your trial ends tomorrow notification could fire for people who never started a trial. I removed it and cancel any already scheduled copy on launch, so a message queued on an old build cannot still arrive. A scheduled local notification is a promise made in the past, so when the rule changes you have to go back and cancel what you already scheduled.

Links