Skip to content

A fitness app people actually keep using

A mobile fitness app that turns daily workouts, activity history, and goals into a simple routine people stick with past the first month.

06:52
Tuesday 14 Oct

Morning, Priya

PS
Streak

4days turning up

Misses dim
MTWTFSS

3.8 sessions a week · rolling four weeks · 148 this year

Up next · your Tuesday

Push · Upper A

Last time Tue 7 Oct · 44 min · Bench 80 kg × 5 · 6 exercises

Start · pre-filledSwap
Goals this weekAll 6
Sessions a week4 / 4
Steps a day8,420 / 8,000
Sleep 7 h3 of 7 nights / 5 of 7
TodayHistoryLogGoalsMe

What the engagement involved

Industry
Healthcare & Dental Practices
Duration
12 weeks
Cooperation model
Fixed price, phased
Services
Mobile designReact Native buildHabit loops
Integrations
HL7 FHIRTwilioStripeDocuSign
Technologies
React NativeTypeScriptNode.jsPostgreSQLTailwind CSSApple HealthKit
Team
1 Project lead1 Product designer2 Mobile engineers1 Backend engineer1 QA engineer

Client name withheld under NDA. Engagement details are shown to the extent our agreement permits.

Introduction

What we were brought in to do

Users logged workouts for two weeks, then dropped off. We redesigned the app around a habit loop that survives real life.

An app with strong installs and a retention curve that fell off a cliff at day fourteen, the point where the novelty of a new tracker runs out and the friction has to be worth it. The team had been adding features to fix it, which had made logging slower. The engagement was scoped around a single number, thirty-day retention, and everything was judged against it.

Product Design & Build

Where the old way broke

  • Generic tracking felt like a chore, so people lost sight of progress and quit after a few weeks.

    Logging a workout took eleven taps and forty seconds because every field was empty every time, including the ones that had held the same value for six weeks. Session data showed people abandoning mid-log more often than skipping a workout entirely. They were turning up at the gym and giving up on the app: the worst possible failure for a habit product.

    We designed a focused logging flow, a clear history view for spotting trends, and lightweight goal-setting that slots into a daily habit without adding friction.

15-Second Workout Logger

Fast workout logging built around habit formation and as few taps as possible.

The logger opens on the workout you did last, pre-filled with last session's weights, so the common case is confirm-and-close. Everything writes to a local SQLite store first and syncs after, which makes it usable in a basement gym with no signal. Nothing in the flow blocks on the network, and no screen in it asks a question the app could answer from history.

What shipped
  • Opens pre-filled from the last session's numbers
  • Local-first writes; the network is never in the path
  • No field the app could fill from history
07:31

Push · Upper A

Started 07:12 · 3 of 7 exercises

18:40
No signal · 9 sets saved on this phone, sync later

Bench press

Set 3 of 5
Weight

82.5kg

Last week 80
Reps

5

Last week 5
Confirm set
82.5×582.5×580 × 580 × 580 × 4
Rest1:24
This session · weights from last time
Warm-up press2 × 1040 kg
Bench press5 × 580 kg
Incline dumbbell press3 × 826 kg
Seated shoulder press3 × 822 kg
Cable fly3 × 1212.5 kg
Triceps pushdown3 × 1225 kg
Finish session On phone
On screen

Mid-session with no signal: set three of bench press at 82.5 kg with last week's 80 beside it, weight and reps already filled so the set is one confirm, the rest timer running, and every set saved on the phone to sync later.

07:05
Friday 24 Oct

Yesterday got away

Streak held

9days · 1 dimmed

Thu missed

A missed day dims your streak. It doesn't reset it, and nothing here needs making up.

Three short ones, if today allows

Mobility 10 · 10 min

Your usual Tuesday stretch, cut down

Start

Walk it off · 15 min

Counts from your phone's steps

Start

Upper express · 20 min

Three lifts from Push · Upper A

Start
Six months · sessions a weekFrequency, not volume
MayJulAug · a week offOct

The missed week in August didn't move the four-week trend for long.

TodayHistoryLogGoalsMe
On screen

The morning after a missed day: the streak held with Thursday dimmed in the two-week view, three short sessions offered instead of a lecture, and six months of sessions a week showing the one week off in August barely registering.

Consistency & Streak Tracker

Visual trend history that rewards showing up often, whatever the intensity.

The history view plots frequency over volume, because the behavior that actually predicts people staying is turning up. Streaks are forgiving by design: a missed day dims and never resets, after testing showed hard resets pushed users to abandon the month entirely. Trends are computed on a rolling four-week window, so a good week can't flatter a bad month.

What shipped
  • Frequency plotted ahead of volume or intensity
  • Forgiving streaks: a missed day dims, never resets
  • Rolling four-week trend window
21:14

Health sources

Apple Health · HealthKit

Health Connect on Android reads the same way

Last read 21:02 · iPhone and Apple Watch

Asked when you need itNever at launch
Workouts · Read + writeAllowedAsked: first time you finish a run
Steps · ReadAllowedAsked: when you set a steps goal
Sleep · ReadAllowedAsked: when you set a sleep goal
Heart rate · ReadNot yetWithout it: effort from reps only
Body weight · Read + writeNot yetWithout it: type it on the day
Counted once1 duplicate dropped

Easy run · 5.2 km · 06:14

Watch · kept iPhone · same run

Matched on source and timestamp, so your week isn't doubled

Saved on this phone first, then your account. Every feature works with all five switched off.
TodayHistoryLogGoalsMe

Phone Health Source Sync

On screen

Health sources: HealthKit read the same way as Health Connect, five permissions each asked at the moment it's needed with what the app does without it, a run from watch and phone counted once, and everything working with all five off.

Automatic biometric and activity data integration across native iOS and Android APIs.

HealthKit on iOS and Health Connect on Android are read through one normalization layer, so a step count means the same thing whatever wrote it. Deduplication runs on source and timestamp, because a phone and a watch both reporting the same run was doubling people's weekly totals. Permissions are asked for at the point of use, never at first launch, and the app works fully without them.

What shipped
  • One normalization layer over HealthKit and Health Connect
  • Source-and-timestamp dedup for phone plus watch
  • Permissions requested at point of use, never at launch

What we built together

  1. 01

    Cut logging to under 15 seconds for the most common workouts

    Fifteen seconds came from session recordings: below it people log in the gym, above it they mean to do it later and don't.

  2. 02

    Designed a streak and trend view that rewards consistency

    History plots frequency over volume, and a missed day dims a streak instead of resetting it. Hard resets had been making people abandon the month.

  3. 03

    Added gentle, well-timed reminders that stop short of nagging

    Reminders fire against the user's own established pattern, never a fixed hour, and stop after two ignored in a row instead of escalating.

  4. 04

    Shipped and iterated against 30-day retention weekly

    Every change was judged against the weekly install cohort, which is how two features that felt right were built and removed inside the engagement.

Operational results after launch

+37%

30-day retention

+2.1x

Workouts logged/user

4.8★

App store rating

Retention is thirty-day, measured per install cohort so a marketing push can't flatter it. Workouts per user is the median, not the mean, because a small number of very heavy users move the average and never moved the problem. The store rating is the rolling figure for the six months after launch.

Client name withheld under NDA. Figures are approximate, drawn from the engagement’s own reporting.

Process

Phase by phase

  1. Phase 1: Retention & Behavior Audit

    User Churn & Habit Loop Analysis

    Analyzed 30-day retention logs and interviewed churned users to isolate logging friction points and habit decay triggers.

    • Retention Audit Report
    • Habit Loop Model
    • Mobile Usability Study
  2. Phase 2: Micro-Interaction Design

    Sub-15s Logging & Trend UX

    Designed sub-15 second workout logging interactions, streak milestone badges, and non-intrusive notification triggers.

    • Figma Design System
    • Micro-Interaction Prototype
    • Notification Strategy
  3. Phase 3: Cross-Platform Build

    React Native & Health Data Engineering

    Engineered native iOS and Android apps with phone health-source auto-syncing and local SQLite offline persistence.

    • React Native Application
    • Health Data Sync Engine
    • Local Persistence Layer
  4. Phase 4: Store Launch & Iteration

    App Store Deployment & Retention Sprints

    Shipped to App Store and Google Play, running weekly retention iteration cycles that increased 30-day active retention by 37%.

    • App Store & Play Store Submissions
    • Weekly Analytics Dashboard
    • Release Sign-off

Retention by intake Week 8

Every release judged against the cohort that installed with it · updated Mon 5 Jan 2026

Mar – Oct 2025Export CSV
30-day retention

+37%

Per install cohort, vs. before

Workouts logged / user

×2.1

Median, not mean

Store rating

4.8★

Rolling six months since launch

Sessions · 90 days

398,014

Logged or read from health sources

Health permissions

82%

Granted in the moment · 38% at launch

Week-eight retention, eight monthly intakesShare of each intake still logging in week eight

38%→57%

March intake to October intake. Two features in between were built, shipped to one intake and removed when it didn't move.
IntakeInstallsStill logging, week 8ShareRelease that shipped to it
Mar 20252,18438%Baseline · 11-tap logger
Apr 20252,46041%Logger pre-filled from last session
May 20252,31844%Local-first writes, offline logging
Jun 20252,70246%Forgiving streaks — a miss dims
Jul 20252,95549%Frequency history, rolling 4 weeks
Aug 20252,81152%HealthKit + Health Connect sync
Sep 20253,19255%Reminders on your own pattern
Oct 20253,04657%Permissions at point of use
September opened · 3,192

Three sessions in the first week is what decides week eight.

Weekly challenges tabBuilt, shipped to one intake, removed · cohort flat

Personal-best badgesBuilt, shipped to one intake, removed · cohort flat

Nudge rules5 on · 2 switched off

Your usual time

20 min before your own pattern

On

Streak held

Morning after a missed day

On

Short session offer

With a held streak

On

Goal nearly met

Evening, one session short

On

Sleep wind-down

Your bedtime minus 45 min

On

We miss you

7 days inactive

Off · chased lapsed

Come back offer

14 days inactive

Off · chased lapsed

Every rule fires on the person's own pattern and stops after two ignored in a row.

On screen

The retention console: eight monthly intakes since March with week-eight retention climbing from 38 to 57 percent and the release that shipped to each, September's 3,192 opened, and the seven nudge rules with the two switched off.

About our collaboration

01
  1. 01

    A cross-functional team of 5 worked on a fixed price, phased basis over 12 weeks, covering Mobile design, React Native build, Habit loops. We held a standing mid-week checkpoint and wrote decisions down in place of status meetings. Nothing shipped without a live demo first.

    Retention was measured weekly against the cohort that installed that week, and every change shipped behind that number, not a release plan. Two features were built and removed inside the engagement because the cohort didn't move, which was the whole point of measuring weekly instead of reviewing at the end.

What we'd carry into the next one

Simplifying workout logging to under 15 seconds lifted 30-day user retention by +37%.

Fifteen seconds isn't a nice-to-have threshold: below it logging happens in the gym, above it people mean to do it later, and later doesn't arrive.

Visual streak tracking and trend rewards increased workouts logged per user by 2.1x.

Rewarding frequency over intensity is what made the streak survivable. The previous streak rewarded personal bests, which nobody can produce daily.

Phone health-source auto-syncing removed manual data entry friction entirely.

Auto-sync removed the fields people were most likely to guess at, which improved the data as much as the experience: guessed numbers had been polluting the trends.

One missed day, two streak rules

A streak that resets punishes the people most likely to leave.

Play one member's two weeks under the old rule, where a miss zeroes the count, and under the one that shipped, where it dims and three short sessions are offered the next morning. Beside it, week-eight retention for the intake that lived with each. Switch tabs, or use the arrow keys once one is focused.

Day 14 of 14 · one member

10sessions in the streak

MonTueWedThuFriSatSunrestrestmiss10mrest

Carrying on

The dimmed day stays in the history and the count never went back to zero. Offered the morning after:

Mobility 10 · 10 minWalk it off · 15 minUpper express · 20 min

Week-eight retention · measured

March intake38%

Hard-reset streak, eleven-tap logger

October intake57%

Forgiving streak, short sessions, and every release since March

The cohort data found that three sessions in the first week is what decides week eight. That's why a miss should cost a dimmed day, never the whole count.

The two weeks shown are illustrative, replayed fast, and follow what testing showed hard resets doing. The retention figures are measured per monthly install intake; October's carries every release between the two intakes, not the streak change on its own.

Architecture

From a confirmed set to a retention number nobody can flatter

React Native on iOS and Android. The phone owns the write, the server owns the history, and the cohort owns the verdict on every release.

  1. 01 · Trigger
    A set confirmed, a sample readThe logger opens on last session's numbers, so the common case is confirm-and-close, under fifteen seconds.
  2. 02 · Local
    SQLite on the phoneEvery write lands locally first. Nothing in the logging flow blocks on the network, so losing signal loses nothing.
  3. 03 · Normalise
    HealthKit + Health ConnectOne normalization layer, so a step means the same whatever wrote it. Dedup on source and timestamp stops watch-plus-phone doubling.
  4. 04 · State
    Node.js + PostgreSQLHistory kept as frequency over a rolling four-week window. A missed day dims a streak; reminders stop after two ignored.
  5. 05 · Judge
    Weekly install cohortThirty-day retention per cohort and workouts as a median, so a marketing push or a few heavy users can't flatter a release.

Kept sessions, asked permissions, honest totals

Offline-first writes, consent in the moment & deduplicated health data

A logged set never waits on signal

Everything writes to a local SQLite store first and syncs after. Nothing in the logging flow blocks on the network, so a basement gym with no signal still keeps every set.

Health access asked for, never assumed

HealthKit and Health Connect permissions are requested at the point of use, not at first launch, and the app works fully without any of them.

One run counted once

Deduplication runs on source and timestamp, so a phone and a watch reporting the same run no longer double a weekly total, and synced numbers replace the guesses that had polluted trends.

Building an app people need to still be opening in week eight? Scope your build in three minutes.

Scope your build
Have a project?

Let's talk

Running a large platform, shaping a first MVP, or getting a product ready for a funding round? Tell us where you are. We'll shape the process around it, and stay with you after launch.