Skip to content
SPBuilt by Samir
The Lab

Project 3 of 5

Cadence

A consumer mobile app carried all the way through app store submission, not stopped at a demo.

Why this matters to a client

Why this matters to a client

Most technology pitches stop at a working prototype. Native mobile is where that gap shows fastest: platform health-data entitlements, push notification certificates, app store submission, a real device build pipeline — none of it is optional, and none of it is visible in a demo. I built and carried a consumer iOS app through that entire pipeline on my own, so I know where that path actually breaks before I recommend a client fund it.

What it does

What it does

Cadence is a fitness-coaching app that adjusts its guidance to how the user actually is that day — sleep, prior training load, soreness, energy — rather than running a fixed program regardless of state. A deterministic rules engine computes a readiness score from that data; an AI layer turns the score into a written coaching response, but never overrides it.

Product screenshots

Cadence home screen showing today's readiness score and coaching summary
Home — today's readiness score, computed by the rules engine.
Cadence conversational coaching screen with a chat-style AI response
Coaching conversation — the AI layer's written response.
Cadence daily reflection input screen
Reflect — the daily inputs the readiness score is computed from.
Cadence insights screen showing trends over time
Insights — trends surfaced from accumulated daily data.
Cadence settings screen
Settings — account, notifications, and health-data permissions.

How it's built

How it's built

Technical detail
Skip ahead

For readers who want the engineering — skip ahead if you just want the outcome.

React Native on Expo, TypeScript, Zustand for state, Supabase for backend and edge functions, on-device health data, and Claude for the conversational layer — a cheaper model by default, upgraded only when the interaction calls for it, with a hard daily cost cap that downgrades automatically if exceeded. A keyword-based safety gate screens for medical or crisis language before anything reaches the AI at all. Full native iOS project with a real app store submission pipeline.

The interesting decision

The interesting decision

The AI layer is told, explicitly, that if the rules engine says the user needs recovery, it must recommend recovery. That instruction isn't trusted on its own: a second, deterministic check reads the AI's actual generated text for phrases like "push hard" or "max effort," and if it finds one that contradicts a recovery day, it throws the AI's answer away and substitutes a fixed, pre-written response instead. It's a narrow, almost crude check — a keyword list, not a second model call — but it reflects a real judgment: don't let a generative system have the last word on something that could affect someone's health, even after you've prompted it correctly.

The same instinct shows up in what's missing. Error tracking hit a launch-crashing bug twice in earlier versions, both times traced to the crash-reporting library's own native init code running before the app could recover from it. Rather than fight it a third time, the reporting calls were replaced with a stub that logs to the console and does nothing else, with the failure history written directly into the code as a comment so the mistake doesn't get repeated blind.

Status

Status

Built and shipped through app store review — health-data and push entitlements, a registered developer account, a native build, live on the App Store. Running for personal use, not commercialized; a small number of unrelated test failures are outstanding and error tracking currently runs as a documented no-op after two earlier crash-on-launch incidents.