Back to projects
Case study P/01 Shipped 2025 iOS / macOS Solo

Loopy - a habit tracker that argues back.

A local-first habit tracker for people who hate habit trackers. Streaks, but quieter. Reminders, but funnier. The "you missed a day" message is a small on-device roast tuned to be annoying enough to work and gentle enough to keep you opening the app.

RoleDesign + iOS + Rust core
TimelineAug 2024 - Mar 2025
StatusShipped, v1.4
Linkloopy.app

01Context

I had tried six habit trackers and uninstalled all of them within nine days. The pattern was always the same: I'd set up the app on a Sunday, feel briefly virtuous, miss a day, see a giant red broken-streak icon, feel slightly worse than before I installed the app, and uninstall it.

The problem wasn't the tracking. The problem was the tone. These apps were yelling at me like a 4am drill sergeant for forgetting to floss. I wanted something that nudged me like a friend who knew when to shut up.

02The problem

Three things, in order of how much they bothered me:

  • Streak anxiety. The streak is a hostage situation. Lose one day, lose the streak, lose the user. Apps treat this as a feature.
  • Bad timing on reminders. Reminders fire at the same time every day, regardless of what you're doing. This is how an app becomes an enemy.
  • Cloud bloat. No tracker I tried respected the fact that habit data is, at most, a few kilobytes per month. Most demanded an account, a sync, and a paid tier.
"If your reminder app has to apologize, the reminder is the problem, not the user." - a note I wrote on the back of a receipt at month 1

03Approach

I built Loopy around three constraints I refused to break:

  1. Data lives on the device. Sync is opt-in via CloudKit. There is no server.
  2. Streaks are real, but they are quiet. They live on a detail screen. The home screen shows something more honest.
  3. The roast is on-device, model-generated, and tuned for tone. No telemetry leaves the phone, not even crash reports without consent.
[ HOME SCREEN MOCK - drop a screenshot or video ]
Fig. 01 - the home screen. No red, no shame, no streak.

04Design choices

The biggest design decision was what to put on the home screen instead of a streak. After three weeks of trying versions, I landed on a small textual phrase: "Showed up 5 of the last 7 days." It's the truest sentence about a habit, and it doesn't punish a single bad day.

For typography I went with system font at heavy weights, with one accent monospace for numbers. Everything is grayscale except a single calm green tag for "showed up today" - the color shows up exactly twice per day, max. Scarcity makes color mean something.

05Stack

One iOS app, one tiny Rust core for the parts that need to outlive the platform.

app/        SwiftUI 5 - all UI, animations
core/       Rust   - habit model, scheduling, roast tuning
shared/     UniFFI - shared types, generated bindings
data/       SQLite - one file per device, no server
sync/       CloudKit - optional, e2e, opt-in

The roast model is a 380 MB Llama-class distill, quantized and bundled. It runs in <200ms on an A17. It never sees the network. I am, on principle, allergic to features that require a server for a thing that fundamentally doesn't.

06Outcomes

Loopy shipped in March 2025. It is small on purpose. The numbers are also small on purpose. I count them anyway.

12k
Downloads
4.7
App Store rating
41%
D30 retention
0
Telemetry events

The reviews I keep are the ones that say "this is the first habit app I haven't deleted." The reviews I do not keep are the ones asking for a streak on the home screen. The streak is on the detail screen. It is fine where it is.

07Learnings

  • Tone is a feature. It's the feature, on this product.
  • Local-first is a UX choice as much as an engineering one. Users can feel the absence of a sign-in flow without being able to name it.
  • An on-device model is a constraint that improves the product. A bigger model would have made the roasts worse - more generic, more polished, less specific. Smaller forced me to handwrite the system prompt with care.
  • Build the second screen first. The home screen was the last thing I designed. Everything else informed it. If I'd designed it first, it would have a streak on it.