- Client
- Team Garin (online sports coaching)
- What we did
- Sports coaching platform: client app (training, nutrition, community, gamification, check-ins) and web panel for the team (plans, follow-up, moderation), on a multi-tenant foundation with recurring billing — plus the migration of the previous generation's base
- Platform
- iOS and Android app (React Native · Expo · RxDB local database) · Web panel (React + Vite) · NestJS API · MongoDB · AWS (Elastic Beanstalk, S3) · Stripe · Expo Push
- 1,168 clients
- registered on the platform as of September 2, 2026 — and since October the whole base runs on the new app
- 416K sets
- logged with load and reps (99% filled in) as of September 2, 2026, carried over with the same identifiers
- 49% · 62%
- of the base trained that week and that month, on September 2, 2026: the usage the new generation inherited
- 444 active clients
- on Team Garin Pro, the new app, as of October 23, 2026
The starting point
Team Garin sells coaching: a trainer and a nutritionist build the plan, the client follows it and the team adjusts. The first generation of the platform, also built by Epicora, handled that — and the database showed it handled it well. As of September 2, 2026 there were 37,237 workouts logged, averaging 7 exercises and 11 sets per session, with load filled in on 99% of sets. Clients weren't just checking in: they were recording what they lifted. On the other side, a team of 8 people running the daily operation made about 1,220 plan revisions a month.
The measurement was done precisely to find what usage wasn't showing — and the old product had no navigation telemetry, only what becomes a database record, so every number is a floor. Even so, the gaps were clear. And there was an architectural limit: the first generation ran one deployment and one database per coaching business, each with its own app in the stores. It served Team Garin; it couldn't serve the next one.
- 39% of the base was idle — 292 clients dormant or who had never trained — and no automatic trigger to bring them back: the system's only two notifications fired when the team published a plan.
- Cancellation was decided in the first month: 49% of those who left never logged a single workout. The challenge wasn't keeping people who trained — it was activating people who arrived.
- The food diary never caught on: only 25% of clients with a meal plan logged anything in a month, and falling, and 86% of the daily diet records the system pre-generated never received a single entry.
- Features nobody used and data that was missing: the check-in module had zero responses, the data model didn't link clients to their trainer or nutritionist, and perceived exertion had silently stopped being saved.
The turning point
The decision was to design the new generation around the snapshot, not a wish list. The core — workouts logged set by set — stayed intact and got what was missing around it. A client who drifts away needs a reason to come back that doesn't depend on the team remembering them: hence gamification, which scores completed workouts, personal records, logged meals, answered check-ins and community posts, with achievements for streaks, volume and time with the coaching business and an all-time and quarterly ranking; and the community, where clients post their workouts, share achievements and get likes and comments from the people they train alongside.
Every database finding became a decision in the new system. The day's diet stopped being pre-generated for every client and is now created on the first entry or first read. The client membership gained responsible professionals, and the panel can slice the roster by staff member. Workouts record perceived exertion again, and check-ins became recurring follow-up — weekly, biweekly or monthly, sent in bulk and reviewed by the team. And logged meals and answered check-ins now earn points: the behavior the old product never reinforced finally has reinforcement.
The third decision was architectural: one platform, many coaching businesses. Every record carries the business it belongs to, and isolation doesn't rely on each query remembering it — a database plugin injects the filter into every read and write, and a query with no tenant set fails instead of returning everyone's data. On top of that: recurring billing through Stripe, self-service sign-up for coaching businesses, per-workspace theme and logo, and a single client account that can belong to more than one business. Team Garin is the first workspace; the foundation for the next one is already in the code.
The new app is a different store listing: nobody gets an update, every client has to download it. So the base didn't switch over all at once. The migration ran in batches chosen by the coaching business, with the old system serving whoever hadn't switched yet. Each batch goes through a dry run before writing anything, arrives with the same identifiers as the old database — workout, diet and weight history point to the same records, no remapping — and the same password, and ends with an automatic collection-by-collection recount. The recorded batches closed with zero discrepancies, and by October the whole base was running on the new app.
What we delivered
01 · The client app, which works with no signal at the gym
Training, meal plan, weight and history live on the device, in a local database synced with the API: clients train and log offline, and everything goes up when the signal returns — points included, because they're credited on the server when the sync arrives. During a workout the iPhone shows the session on the lock screen; on the home screen, a widget with a training heat map. The last load shows up in the prescription, personal records are detected set by set, and each exercise's progress becomes a chart. When the session ends, the workout becomes an image ready to share.
02 · Gamification with accounting rules
Points for completed workouts, personal records, complete meals, answered check-ins and community posts, each value set by the coaching business; automatic achievements (streaks, volume, records, workouts, meals, check-ins, time as a member) and manual ones granted by the team; an all-time and quarterly ranking, with each quarter closed and stored automatically. Underneath, an immutable ledger: points are never deleted or edited, and a correction is a reversal entry, like a card chargeback. Changing the points table doesn't rewrite the past, the same workout never scores twice, and stopping training resets the streak but never takes points away.
03 · The coaching community, with real moderation
A feed with text and up to 4 photos per post, likes, comments, posts pinned by the team and achievements shared straight from the app. Likes arrive grouped, Instagram-style, and clients turn each notification category on or off — community, gamification, coaching, account. The team moderates from the panel: reports become a Reported Content queue, with actions to hide, keep or restrict a client's community access; and clients can block another client, as the App Store requires for apps with user-generated content. Post photos are private and only open through signed, expiring links.
04 · The team panel: the whole roster and each client up close
The panel opens on an operational dashboard: active clients against the plan limit, check-ins awaiting review, reports to moderate and the ranking podium. Opening a client puts the team in Client Mode — summary, training, nutrition, check-ins, points, support material and subscription in one place. Follow-up check-ins go out recurring and in bulk, with side-by-side progress photos; plans come from the business's own templates; and each client has responsible professionals, the slice that was missing to see each trainer's and nutritionist's roster.
How we made it safe
A migration that only writes after rehearsing
The migration script reads the old database and never writes to it: until the first new record exists, rolling back is just reopening the old system. Every run starts in dry-run mode, which shows what will happen and stops on any blocker — an email already on the platform, a numeric identifier already taken, a missing catalog item. Writing is idempotent (running it again rewrites the same thing, it doesn't duplicate) and ends with a recount that checks, collection by collection, what reached the destination.
Legacy mess cleaned up without losing a document
The rehearsal against the real base found what the old database tolerated and the new one doesn't: 38 duplicated emails across 115 accounts, leftovers from re-sent invitations. No email had two live accounts; the active account kept the address, the already-deleted leftovers got a reserved address that is never delivered, and every document kept the same identifier. The same applied to orphaned profiles and repeated numbering: every fix written to the migration report, nothing silently dropped.
Health data locked down by default
Assessment photos, documents and post photos live in private storage, per business and per user, and only open through signed links whose lifetime depends on sensitivity — 5 minutes for check-in photos, 15 for documents. The API checks that a referenced file belongs to whoever sends it, and isolation between businesses is enforced at database access, not screen by screen. Account deletion happens inside the app, as the stores require, and production errors land in our own monitoring.
The outcome
The number that matters most in this case is still being written — which is why it comes with a date. As of September 2, 2026, still on the previous generation, half the base trained every week, about 156 clients a day, at ~11 workouts a month per active client. That's the floor: the usage that already existed with no community, no gamification and no trigger for idle clients. Since October, Team Garin's entire base trains and posts on Team Garin Pro, published on the App Store and Google Play: on October 23, 2026 there were 444 active clients on the new app and 204 posts in the community.
And the platform running the business today isn't a single-business app. Workspace isolation, recurring billing, self-service sign-up and a theme catalog are already in the code, with Team Garin as the first tenant. The next step is turning that foundation into a product for other coaching businesses — built on the real operation of a business with over a thousand registered clients, not on a demo.
Do your clients log their workouts but have no reason to come back tomorrow?
Epicora builds the platform for your operation from measured usage — an app that works at the gym, gamification and community with real rules — and with the foundation ready for the day it becomes a product.
