Skip to content
Stride

Stride

A personal tracking tool built to solve my frictions.

2026Live

Most wellness apps try to do everything for everyone. They're bloated, they decide what you should care about, and they lock your own data behind a subscription. I wanted something simple - something that tracks what actually matters to me, shows the trends over time, and then gets out of the way. Also, I own my data.

I built this entirely with Claude - first app I've ever made (I know it looks very vibecoded). It took about 50 full iterations to get here, and along the way I learned more about design and development than I thought I would. The motivation was to reduce friction in tracking my physical activities: I needed one place to track gym, tennis, mood, and weight. I use it daily now - or at least I try to, until Supabase tells me it will pause the project due to inactivity. It's built to reduce a personal pain point. That's the feature.

stridehealth.vercel.app
461commits
6milestones
24phases
4design systems
1DROP TABLE
01

First Impression

The sign-up screen sets the tone. Animated light beams trace the card border, a subtle animated gradient sits behind it. Email and password auth with clear error states - no friction, just get in and start tracking. I added Google Sign-in options to delve a bit into the process of setting up authentication with Google. I learned that I had to create ToS and Privacy Policy pages for approval.

Sign-up screen.

Mood tracker: trend line, calendar heatmap, and rolling averages.

02

Mood Tracker

Rate your mood from 1 to 10, and let the patterns surface on their own. A line chart tracks recent trends, a calendar heatmap gives you the full year at a glance, and rolling averages show where your head's been over the last 7 and 30 days.

03

Activity Log

Log workouts by exercise, sets, reps, and weight. Activities like running, tennis, or swimming get tracked by duration instead. Over time, Stride plots your progression - so you can see whether you're actually getting stronger or just showing up, which is completely fine by the way. I later added the option to easily manage these logs.

Activity log: weight-based and duration-based exercise tracking.

Intensity normalised to your personal best: a fair view of effort across any lift.

04

Activity Intensity

Rather than plotting raw weight, Stride calculates intensity relative to your personal best for each exercise. A tough bodyweight session reads the same as a heavy squat day. It's a fairer view of effort across different movements.

05

Progress Tracker

Track weight and BMI over time with clean line charts. Stat cards give you a quick read on where you stand, and trend indicators show which direction you're heading. RLS enforced, obviously. This is really helpful for me, since I am trying to put on some weight.

Progress tracker: body weight and BMI trends with RLS-enforced privacy.

The build

Built before it was planned

The first commit is literally called "Initial commit". The ones after it are called things like "Update page.tsx", "New testing...", "Habits fixed v3", and the classic, "BIG GRAPHS". No phases, no roadmap - just an app called Life Analytics growing in whatever direction I let Claude push it.

And it worked, sort of. In three weeks the app had mood tracking, habits, a gym log, weight tracking, a mobile overhaul with bottom tab navigation, and real authentication. But the commit history tells the vibecoded story: the same habits page was "fixed" at least five times, errors kept resurfacing, and every fix risked breaking the thing next to it.

The turn came three weeks in. Full of breaking things and asking Claude to fix the same things, I stopped and did what I should have done on day one: write down the requirements and create a detailed roadmap. From this point on, everything shipped through versioned milestones - each one planned, executed in phases, audited, and closed with a written retrospective. I basically brought in the engineering lifecycle after building the thing. The commit log splits cleanly in two:

git log · before the turn
  • 004a553Fix TypeScript Set iteration
  • 747b951Update page.tsx
  • 6c60f1aTesting new fixes
  • c0042b0New modifs
  • 85f3be7Habits fixed v3
  • 57689afNew testing...
  • f84e8abBIG GRAPHS
git log · after the turn
  • 595612cdocs: map existing codebase
  • bec1ccadocs: initialize project
  • 8c41f02feat(03-01): add RLS policies for mood_logs
  • b12e7aafeat(17-01): create lib/chart-theme.ts
  • d40c9e1feat(22-01): create usePalette hook
  • 87169b5feat(types): typed Supabase client
  • 06bb847feat(ui): final polish - optimistic writes

Two decisions from the scrappy era did stick. Supabase for everything backend - auth, Postgres, row-level security, storage - one service, no servers of my own; the app talks to the database directly, and RLS policies are the security boundary. And a roles idea worth keeping: my friends wanted the gym tracker but not my mood data, so a GymUser role saw only the gym and weight pages. The app was multi-user from week three, so security had to actually work.

The turn

Six milestones

v1.0
The scrappy eraMood, habits, gym, weight, auth - built on vibes and bug reports.
Feb 02 – 22
v1.1
Security & PolishRLS hardened (role check AND ownership on every table), the service key kept off the browser, and a migration that moved existing data with zero errors.
Mar 04
v2.0
Visual OverhaulThe deep-navy identity, an animated SVG wave background, a bento dashboard, and a gym calendar with per-exercise progression deltas.
Mar 08
v3.0
Visual Polish & ConsistencyExecuted in a single day - and where the habits funeral happened.
Mar 11
v4.0
Activities & UI PolishThe rebrand. "Life Analytics" was a description; Stride is a name. Plus a proper profile page and fully dynamic activity types.
Mar 12
v5.0
Animation, Charts & PolishAll seven charts refactored onto one CHART_THEME source, skeleton loading everywhere, empty states, and an exercise history that remembers what you lift.
Mar 12
v6.0
Themes & RefinementA theme picker (rose, forest), a pure-black AMOLED midnight theme, and toast notifications tweaked to not be intrusive.
Mar 16
>6.0
The long polishGlassmorphic redesign, security audit, OAuth + GDPR, PWA install, final UI review.
Mar – Jun
Subtraction

Scrapped functions

Habits was one of the launch features. It was also the buggiest page in the app, the one "fixed v3", and - more importantly - the one I just stopped using. Mood, gym, weight: logged daily. Habits: gave up.

So in v3.0 it didn't get fixed again. It got deleted. Page removed, nav link removed, queries and types removed, and a migration that ends in DROP TABLE habit_logs.

In memory of

Habits

Feb 02 – Mar 08, 2026 · launch feature · fixed v1, v2, v3 · used for two weeks
-- migrations/drop_habit_logs.sql
DROP TABLE habit_logs;

The admin panel met the same fate a few days later - built carefully in v1.1, then removed once I accepted that an app with a handful of users doesn't need user management tooling.

Both deletions made the app better than any feature added that month.
Identity

Four design systems, four font eras

The website had a font saga; Stride had a font epic:

Warm ObsidianThe first deliberate identity: dark, amber accents, Cormorant Garamond display with DM Sans. It lasted less than a week - the serif that looked editorial on a photography site looked weird on a data app. (Basically what Claude gave me.)
lasted under a week
Deep navy + tealThe pivot, made mid-milestone via an inserted phase 5.1. Teal-cyan accent, Geist Mono for every number. This is when Stride started looking a bit less like AI slop.
the pivot · phase 5.1
TranslucencyA glassmorphic design: translucent panels, depth, glow. Plus an animation polish round inspired by Emil Kowalski's work - easing, duration discipline.
layered on top
The font convergenceA five-font stack collapsed into Hanken Grotesk + Recursive, and finally into Plus Jakarta Sans. Each reduction made the app feel more like one thing.
shipped ✓

The lesson from the retrospective, written after the palette pivot cost an entire extra phase: lock design direction before execution begins. I learned it; I wrote it down; the website build benefited from it months later.

One pattern outlived every redesign: per-page colour identity. Mood is purple, gym is crimson, weight is sky blue - wired through a single data-page attribute and CSS custom properties.

data-page="mood"data-page="gym"data-page="weight"data-page="dashboard"
Hardening

Security, twice

Because Stride holds other people's gym logs and my own mood scores, I had to make sure it was secure.

The April security audit went looking for issues and found them: a leak in the auth flow, avatar uploads with no type or size validation, a missing DELETE policy on the storage bucket, missing security headers. All fixed, plus in-depth user_id filters in every query - so even if an RLS policy were ever misconfigured, the queries themselves don't trust the session.

RLS
the security boundary
Role check AND ownership on every table - verified by running queries as different roles
4
April audit findings
Auth-flow leak, upload validation, storage DELETE policy, missing headers - all fixed
C1-M11
June review
Findings shipped in four buckets over a single day: quick wins, data safety, structural, polish
2
GDPR features
Data export and account deletion - anyone can leave with everything they logged

Then in June, a full UI/UX review produced findings labelled like a flight checklist (as usual, I asked Claude to give it to me this way) - C1 through M11 - and the fixes went out in four buckets over a single day: quick wins, data safety, structural refactors, polish. The same audit-then-batches pattern I later used on the website. It works: a written review, then mechanical execution.

Multi-user also meant thinking about a bigger privacy picture - Google OAuth forced privacy and terms pages, and I had to add data export and account deletion, so anyone can walk away with their own data.

The final test was when Fable 5.0 was released and I asked it to run another deep security audit. A few issues here and there again - nothing critical, and all fixed now.

Behind the Build

Key Technical Decisions

  • Multiple exercises in one gym session share a workout ID. Easy to group, easy to display, no need for a separate sessions table.
  • Heavy chart components are lazy-loaded so the dashboard loads fast and charts stream in when you actually need them.
  • Intensity is scored relative to your personal best per exercise - a normalised view of effort that works across any lift.
  • Enabled PWA support so I can add it to my home screen without needing to get into Android development (for now).
For the road

What I'd tell you if you're building one

  1. 01
    Fully vibecoding it first is fine - but it will come back and bite you later.

    Three weeks of chaos taught me what the app wanted to be. Starting without a plan was fine; never stopping to make one from the rapid prototypes was the actual mistake.

  2. 02
    Delete the feature you don't use.

    Your own behaviour is the only honest user research a personal app gets. I stopped logging habits long before I admitted the feature had failed.

  3. 03
    Take RLS seriously from the start.

    I verified every policy by running queries as different roles. It felt paranoid, right up until the audit found a real gap.

  4. 04
    Write retrospectives, even solo.

    Every milestone closed with what worked, what was inefficient, and lessons.

  5. 05
    Charts deserve a design system.

    Seven charts each styling themselves looked like seven slightly different apps. One CHART_THEME constant ended the drift.

  6. 06
    A personal app is allowed to be opinionated.

    There are no streaks, badges, or notifications begging me to log. If I skip a few days, Stride just waits.

The website was built like a proper end product that had clear goals and a development lifecycle. Stride was built without much structure, and that was a massive learning point. Four months later it's the app I actually open every other day, which is the only metric that ever mattered in the first place.

Stride · built February – June 2026 · Next.js · Supabase · Recharts · Framer Motion