What it is
MyFit is a workout tracker built around the same progressive overload and RIR-based training philosophy as the RP Hypertrophy app. RIR (reps in reserve) is how many more reps you could have done at the end of a set.
Some of what it actually does:
- Progression formulas adjust your next workout based on logged reps, load and RIR.
- You can change your split mid-mesocycle without losing history. A mesocycle is a multi-week training block.
- Drag-and-drop exercise reordering, which people had been asking for since v1.
Rebuilding it three times
I have rebuilt MyFit three times. v2 alone drew 10,000+ views a month before I replaced it. Each version's foundation could not support what I wanted to build next.
What v2 got wrong
v2 failed mainly on types. The API was REST on top of MongoDB, so I typed every request and response by hand, and I disliked that work. The UI library also felt dated by then.
What v3 changed
- PostgreSQL instead of MongoDB. I wanted relational safety, native joins that give Prisma accurate types, and a database I could rely on.
- tRPC end to end. The server and client share one type system. SvelteKit's types for server-side rendering and page
loadfunctions extend it to the pages. This was the biggest quality-of-life gain. - shadcn/ui for the interface. I wanted to try it, and it replaced the old component library.
- Svelte 5 with runes for the UI.
I chose CockroachDB for its free tier. I did not need distributed SQL. The rewrite took longer than I promised, because I made myself slow down after watching the v2 codebase degrade under real usage. v3 shipped with a one-click migration tool, so existing users kept their workout history.
The production incident
During v4 work, I ran prisma db push against a separate v4 database on CockroachDB Cloud, the same platform that hosted v3. The command dropped a few columns and ran for minutes. I took it for latency and went to play a game. A warning email said 50% of the month's Request Units were used. A Request Unit is CockroachDB Cloud's measure of the work a query does. When I looked again, usage had reached 100% and the database refused connections, including the production app's.
I put a notice on the app that said it would return when the next month started. I tried to move the backups to another platform and could not export them. In the end I added a payment card to the account, which fixed the outage within hours. The three lessons in my post: do not pick a platform out of laziness, read usage warnings, and stay calm. The full story is in When I Broke Prod.
What comes next
v4 is the next rebuild. Its foundation is prisma-idb, my Prisma client for IndexedDB. The goal is an app that works fully offline, syncs when the connection returns, and keeps authorization checks and data safety on the server.
I wrote more about this project than any other: Building MyFit v3, Suboptimal, MyFit V3 is Live and When I Broke Prod.
How it works
MyFit v3 is a SvelteKit app that installs as a progressive web app (PWA). The browser talks to the server through tRPC, and the server talks to the database through Prisma. The database is CockroachDB, which is PostgreSQL-compatible.
| Layer | Location | Job |
|---|---|---|
| API | src/lib/trpc/routes/ | Four routers: workouts, mesocycles, exerciseSplits, users |
| Schema | prisma/schema/ | Prisma schema split by domain: users, enums, splits, mesocycles, workouts |
| Validation | src/lib/zodSchemas/ | Zod schemas generated from the Prisma models |
| Progression | src/lib/utils/workoutUtils.ts | Overload calculations |
| Offline | src/service-worker.ts | Caching and an /offline fallback page |
| Migration | src/lib/trpc/routes/users.ts | Checks for v2 data and imports it from MongoDB |
The data model is hierarchical. A user owns exercise splits (reusable weekly templates), mesocycles (training blocks) and workouts (logged sessions). Creating a mesocycle copies a split into the mesocycle, so edits to the block leave the original template alone.
The progression code uses the Berger formula. solveBergerFormula solves for the reps in the next set, given the previous set, an overload percentage and bodyweight where the exercise uses it. It also handles mini-sets, which model drop sets and similar set types.
Design decisions
One type system from database to UI. Prisma defines the models, zod-prisma-types generates Zod validators, and tRPC shares the router types with the Svelte client. This replaces the REST API of v2.
Copy the split into the mesocycle. The project's architecture notes say the copy can be modified independently of the template. This supports changing a split mid-mesocycle. The likely cost, by inference, is duplicated rows.
Cache static assets, not data. The service worker serves styles, fonts, images and some pre-rendered pages from cache and sends API calls to the network. When offline, it shows a fallback page. By inference, workout logging needs a connection.
Automated migrations and releases. A workflow runs prisma migrate deploy against production when files under prisma/migrations change on main. release-it produces versioned releases with a changelog.
Run it locally
Prerequisites: Node.js, pnpm and a CockroachDB instance. The repository includes a dev container with CockroachDB.
-
Clone the repository and install dependencies. The install step also generates the Prisma client.
git clone https://github.com/WhyAsh5114/MyFit.git cd MyFit pnpm install -
Copy
sample.envto.env. SetDATABASE_URLandAUTH_SECRET. Generate the secret withnpx auth secret. -
Apply the database schema.
npx prisma migrate dev -
Start the development server and open
http://localhost:5173.pnpm dev
Sign-in uses Google or GitHub OAuth. To skip OAuth with direct database access, run pnpm create-user to create a test user. To run the Playwright end-to-end tests, run pnpm test.
Reference
| Area | Choice | Used for |
|---|---|---|
| Frontend | SvelteKit 2, Svelte 5 runes, Tailwind CSS, bits-ui | Interface and state |
| API | tRPC | Type-safe client-server calls |
| Data | Prisma 6, CockroachDB | Storage and migrations |
| Auth | Auth.js with Google and GitHub | Sign-in and sessions |
| Charts | Chart.js | Progress and statistics views |
| Drag and drop | svelte-dnd-action | Exercise reordering |
| PWA | Vite PWA plugin, Workbox | Install and caching |
| Testing | Playwright | End-to-end and progression tests |
| Delivery | Vercel, GitHub Actions, release-it | Hosting, CI and releases |
Outcome
- MyFit is live at myfit.fit and released under AGPL-3.0.
- The repository dates from 2023-06-03 and has 142 GitHub stars.
- The v3.0.0 release is dated 2024-10-17, the same day as the "MyFit V3 is Live" post.
- GitHub lists 43 releases. The latest, v3.21.1, is dated 2026-08-29.
- GitHub Actions runs lint, type checks and Playwright tests against a CockroachDB service on each push and pull request to
main.