loading...

AI Project: Fitness App
A personal fitness tracker built entirely by directing Claude: no prior coding background. It tracks gym sessions, cardio, and stretching, with progress and streaks, injury-safe exercise selection, built-in variety so routines never go stale, and data that syncs across every device. Built to solve a specific rehab problem no off-the-shelf app quite fit. Demo login on request → hello@loe.kim

Why I built it

This was my first project as a builder rather than a writer of prompts alone. I had a nagging groin/glute injury that needed specific rehab, a general fitness goal on top of it, and a habit of getting stuck doing the same exercises and stretches on repeat. I looked for an existing app that would track my progress, steer me toward exercises that respected the injury, and keep enough variety that I’d actually stick with it. Nothing quite fit, so I built it.

The journey

1. Planning before a single line of code

Before opening Claude, I mapped the app out, on paper, starting with the daily flow, what a "session" actually consists of, what needed to sync across devices, and potentail rules and option trees. That brainstorm became a written project brief, which became the first prompts, setting up a back-and-forth planning dialogue with Claude.

Claude
Kim
Context
I want to build a personal fitness tracking app. The core use case is training and recovery logging, with a specific focus on rehabbing a groin/glute injury alongside general gym, cardio, and stretching work. This isn't a generic fitness tracker: the injury-management angle should shape the data model and daily flow from the start, not get bolted on later.
I don't want any code yet. Before we write a single line, I want us to work through two things together:
1. The core screens: what I actually see and tap through in a day
2. The data model: what we're storing, how it's structured, and how it relates
How I want to work through this
I'm going to describe how I want the daily flow to work: what a typical day of using this app looks like for me, from opening it to logging a session to checking on rehab progress. As I describe it, I want you to:
  • Ask clarifying questions before locking anything in. Don't assume defaults on my behalf, especially anywhere the injury tracking intersects with regular training.
  • Surface tradeoffs, not just options. If there are two reasonable ways to structure something, tell me the tradeoffs of each rather than picking one silently.
  • Push back if something I describe will paint us into a corner later. I'd rather hear it now than discover it after the data model is built.
  • Keep it scoped to planning: screens and data model only for now, no tech stack decisions, no code, no UI polish, until we've locked both down.
What "locked in" looks like
Before we move to implementation, I want us to have:
  • A list of core screens with a one-line purpose for each, and how they connect
  • A data model: entities, key fields, and relationships, that explicitly accounts for regular training, rehab-specific tracking for the injury, and anything that needs to persist across days (progress, trends, symptoms, PRs)
Where I'll start
I'll describe my ideal daily flow first: open the app, what I see, what I log, in what order, and what I want to check back on. Ask me questions as I go rather than waiting until I'm done.

2. Building the core loop

The first real version was the daily loop: Morning Stretch, Cardio, Gym, Evening Stretch, plus a Progress view and an exercise library. The interesting decisions weren't the screens themselves, they were the rules underneath: what counts as a "complete" day, how a streak breaks, and how gym exercises get picked so the injury never gets aggravated and each session targets the correct muscles, in the correct order, and with variety.

3. From prototype to real software

The initial build existed only as an ephemeral browser session: no persistent storage, no user accounts, and no state once the tab closed. The next milestone was making the app survive beyond a single session, persisting across devices so it would follow me between phone and laptop. That required introducing a genuine backend, including authentication and cloud-based data storage.

Since I had limited prior experience with backend architecture, authentication systems, or cloud databases, I approached this phase as a guided learning process, working alongside Claude as a tutor who explained not just the implementation steps but the reasoning behind each decision. Concretely, this meant hosting the app as a page within my personal website and integrating Firebase to handle authentication and cloud data storage.

4. The debugging arc

This stage was where the real engineering work happened. Some of the bugs encountered were genuinely serious, including several that cost significant data.

As the app grew in complexity, it became essential to diagnose issues methodically, working through hypotheses and root causes collaboratively with Claude rather than applying surface-level fixes. This process included prompting Claude to hardcode starter data and build functionality for editing, adding, downloading, and uploading data.

Notable issues included:

  • A silent write failure: Firestore was rejecting saves because part of the data was structured as an array of arrays, a format it doesn't support. The fix wasn't a simple patch. It required restructuring that data and auditing the rest of the codebase for the same pattern.
  • A timezone bug: entries were being dated in UTC rather than local time, meaning anything logged in the evening sometimes landed on the wrong calendar day.
  • Multiple rounds of race conditions between saving and loading data, which on more than one occasion wiped out session history and progress entirely. Resolving this took genuine back and forth: reading console logs together, forming a hypothesis, testing it, and being honest when the first, and second, fix didn't fully hold.

The lasting solution wasn't patching each bug individually. It was introducing a rolling automatic backup as a genuine safety net, ensuring that a future bug could never again cause unrecoverable damage.

Claude
Kim
Bug Investigation Prompt: Post-6pm Entries Marked as the Next Day
Context
I've found a bug: data added after around 6pm is being marked and stored as the next calendar day instead of today. This means entries logged in the evening are landing on the wrong day, which is corrupting my history and progress tracking.
My working theory, which I want us to test rather than assume is correct, is that the app is treating timestamps as UTC instead of my local time zone. If that's right, anything logged after roughly 6pm local time would cross into the next day in UTC, which would explain the pattern.
How I want to work through this
Treat this as a real investigation, not a quick patch. Specifically:
  • Theorize with me first. Walk through why a UTC versus local time mismatch would produce exactly this symptom (the wrong day, specifically after evening hours, not at some other time). If the evidence doesn't fully support the UTC theory, tell me and help me think through what else could cause it.
  • Find where the bug actually lives. Show me everywhere in the codebase that a date or timestamp gets created, stored, or compared, since a bug like this often hides in more than one place (when the entry is saved, when it's displayed, when it's grouped by day for the Progress view, and so on).
  • Explain the fix in plain language before making it. I want to understand what was actually wrong, not just see a diff. Explain it the way you would to someone who isn't a backend expert: what UTC versus local time means in practice, why the bug only shows up in the evening, and why the fix resolves it rather than just moving the symptom somewhere else.
  • Check for the same pattern elsewhere. If this bug exists in one place, it may exist anywhere else dates are handled. Audit the rest of the app for the same mistake rather than only fixing the one spot I noticed.
Additional feature I want alongside the fix
Since incorrect dates have already caused bad data to be entered, I also want a way to manually correct it. Please suggest an approach for adding the ability to:
  • Manually add an entry for a specific day
  • Edit an existing entry, including its date
  • Delete an entry
  • Do all of the above for previous days, not just today, so I can go back and correct anything that was misdated by this bug
Suggest how this should work rather than just building it silently. If there are decisions worth making together, such as whether editing history should be logged or flagged so I know a day's data has been manually corrected, raise that before implementing it.
What I want from this process
  • A clear, plain-language explanation of every bug found, including this one and anything related that turns up during the audit
  • Confirmation of the root cause before the fix is written, not after
  • The manual add, edit, and delete functionality treated as a real feature, with its own brief design discussion, not bolted on as an afterthought

5. Design system iteration

Once the app was functionally complete, the interface remained purely utilitarian: dark cards with no visual hierarchy. Design isn't a strength of mine, so this stage was deliberately structured as a collaborative process rather than either dictating a rigid specification or ceding creative control entirely to Claude. That balance is the core discipline of effective vibe coding: providing enough direction and taste to keep the output aligned with intent, while leaving enough room for genuine collaborative iteration.

I began by gathering reference material: screenshots of apps, individual UI components, and colour palettes that reflected the direction I wanted. Rather than moving straight into code, the redesign process started with mockups, allowing a visual direction to be evaluated and refined before any implementation commitment was made.

I also set myself one governing constraint early on and held to it throughout the redesign: green is reserved exclusively for signaling completion, never used as a general category colour. It's a small rule, but it's the detail that separates a coherent, meaningful colour system from a palette that simply looks pleasant.

6. Integrating outside the app

By this stage the app was fully functional and stable, with several days of consistent, bug-free use behind it. Through actual daily use, a gap became apparent: steps, a core fitness metric I was tracking against a 10,000-plus daily goal, was missing entirely. I had been relying on a separate app to measure it and wanted that data pulled directly into my own tool instead of tracked in parallel.

I raised this with Claude as a goal rather than a specification. It confirmed the idea was feasible but noted that direct integration with Apple's Health app wasn't possible. When I mentioned that I personally used Pacer to track steps, a deeper search turned up something useful: Pacer exposes a developer API. That opened a real path forward, but it also introduced a genuine technical obstacle: the browser couldn't call Pacer's API directly due to CORS restrictions.

The goal at that point wasn't to route around the restriction with a partial workaround, but to solve it properly. That meant building a small server-side proxy to make the request on the app's behalf, sitting between the browser and Pacer's API. Working through this with Claude, testing possible solutions live as we went, we arrived at a working integration that pulls steps data directly from Pacer into the app, completing the final feature and, with it, the build.

What I learned

The biggest shift wasn't learning to prompt. It was learning to direct.

Specificity was the recurring lesson across every stage of this build. A vague bug report got a vague guess back. An exact console output, an exact reproduction sequence, and a clear description of expected versus actual behavior got a real diagnosis and a real fix, the difference visible directly in how the timezone bug and the Firestore write failure were actually resolved rather than papered over.

The same principle held for testing. Deliberately testing across devices, at odd hours, and against intentionally rough edge cases surfaced the bugs that actually mattered, including the race conditions that put real data at risk, rather than only the bugs that were convenient to stumble across in normal use. Passive testing finds what's in front of you. Deliberate testing finds what's actually broken.

Design worked the same way. Establishing a visual direction through mockups and reference material before any code was written prevented exactly the kind of costly rework that comes from building against a specification that was never actually agreed on. Locking a rule like green meaning "complete," and nothing else, before implementation began is the same discipline as a tight creative brief: it's cheaper to fix a direction on paper than to unwind it in a finished product.

This is the throughline back to the writing and creative-management side of my background. The skill underneath this entire project was never really about knowing syntax. It was about asking good questions, being precise about what "done" actually means before starting, and knowing when a first answer, even a working one, wasn't the right one, and needed to be pushed on rather than accepted.

Building this app didn't require becoming an engineer. It required treating an AI collaborator the way I'd treat any capable creative partner: with clear intent, honest feedback, and the judgment to know the difference between a solution and a shortcut.

AI Project: Fitness App
A personal fitness tracker built entirely by directing Claude: no prior coding background. It tracks gym sessions, cardio, and stretching, with progress and streaks, injury-safe exercise selection, built-in variety so routines never go stale, and data that syncs across every device. Built to solve a specific rehab problem no off-the-shelf app quite fit. Demo login on request → hello@loe.kim