I'm a CS student, and for the last few months I've been building a fitness app in my spare time — the kind of thing where you tell yourself "it's just a workout logger" and three months later you've got offline sync, a food database, Stripe subscriptions and an AI coach. Classic scope creep, but I learned a lot.
Here are the three things that actually ate my time, and how I ended up solving them. (Stack, if you care: Next.js 16 App Router, React 19, Prisma 7 + Postgres, Auth.js v5, Tailwind 4.)
1. Offline workouts that don't lose your sets
The gym I train at has basically no signal in the basement. So "log a set, hit save, watch it fail" was not an option — people would lose a whole workout and rage-quit the app.
The approach that worked: every action (add set, edit weight, finish workout) becomes a mutation queued on the device, with an id generated on the client. When the network comes back, the queue flushes and syncs — idempotently, so replaying the same mutation twice doesn't duplicate anything. The key detail: "finish workout" doesn't resolve until everything in the queue has synced, so you never end up with a half-saved session.
It sounds simple written down. It was not simple. Getting the App Router + a client-side queue + optimistic UI to all agree on the truth took more iterations than I'd like to admit.
2. Stripe, where the webhook is the only source of truth
First version, I did the naive thing: user pays, redirect back, mark them Pro on the client. Don't do that. Any failed redirect or weird tab close and your billing state is a lie.
I rewrote it so the webhook owns everything. checkout.session.completed and the customer.subscription.* events write plan and proUntil onto the user in the DB. The frontend never decides who's Pro — it just reads the DB. Suddenly all the edge cases (cancellations, failed renewals, refunds) handled themselves, because there was one place that knew the truth.
3. An AI coach that costs cents, not a salary
The premium feature is a weekly check-in: the app looks at your training volume, body-weight trend and diet adherence for the week, then suggests progressions and macro tweaks.
The scary part was cost — an LLM per user per week sounds expensive. It isn't, if you're careful. A weekly cron builds a compact summary of the user's week (aggregated numbers, not raw data) and sends that to Claude Sonnet. It comes out to cents per user per week, so a $5/month sub covers it many times over. The trick was resisting the urge to send everything and instead sending the smallest payload that still gives a useful answer.
What I did with it
I built it as a real product first. But shipping another fitness app into a market with MyFitnessPal and Hevy felt like a bad bet — so I packaged the whole thing (offline sync, the Stripe setup, the AI coach, ~870 exercises, the food/barcode stuff) as a starter kit for other devs instead. Rebrand one file, deploy on a free Vercel + Neon stack.
If you want to poke at it, there's a live demo — login demo@atlas.app / atlasdemo, it's got real-looking training history: https://atlas-eta-ochre.vercel.app
And the kit is here if it's useful to you: https://nuttzzz.gumroad.com/l/atlas
Either way — happy to answer anything about the offline sync or the Stripe setup in the comments. That's the part I'd have killed for a write-up on when I started.
Top comments (0)