Skip to content
All projects

Case study

AIthlete

AI-powered workout tracker — build multi-week programs, log every set with demo clips, and let a Gemini coach write sessions straight into your account.

AIthlete screenshot
Role
Full Stack Developer
Timeline
Jun 2025 – present
Team
Solo
Status
In active development
  • Next.js
  • TypeScript
  • Prisma
  • MongoDB
  • NextAuth
  • Google Gemini
  • React Query
  • Tailwind CSS

The hard parts

  1. 01Fanning one session-complete event out to goals, auto-progression and achievements
  2. 02Matching ~6.3k exercise demo clips by name with no stored foreign key
  3. 03Turning free-form AI coach replies into real, editable workout entities
  4. 04Timezone-safe streaks and kg-normalised weights across units

What I learned

  1. 01Designing a domain model around a single write hub
  2. 02Structured (JSON-mode) LLM output as an application primitive
  3. 03Edge middleware vs. database sessions in NextAuth v5
  4. 04Server-only data boundaries for large generated catalogs

AIthlete: Track every rep. Let AI plan the rest.

Overview

AIthlete is a full-stack fitness tracker for people who train with a plan. You build exercises, workouts and multi-week programs, log sessions set by set with a demo clip for every movement, and watch strength, volume and body weight trend over time. An AI coach built on Google Gemini sits on top of all of it — it reads your recent sessions and goals and writes real workouts into your account instead of a wall of text you'd have to re-type.

Key Features

  • Programs, not just workouts: multi-week routines map each (week, day) to a workout or a rest day, and one program can be marked active.
  • Session logging: only the sets you actually check off are saved, and every weight is normalised to kg on write while remembering the unit you entered.
  • Auto-progression: flag an exercise and its target weight bumps automatically after every N completed sessions.
  • Goals that track themselves: stay consistent, lift heavier, do more reps, or hit a body weight — all updated automatically when you finish a session or log a weigh-in.
  • Achievements: first workout, session milestones, 7- and 30-day streaks, lifetime volume and strength-gain badges, evaluated idempotently.
  • Demo media for ~6,300 exercises: user-created and AI-generated exercises get artwork too, because clips are matched by name rather than stored on the row.
  • AI Coach + auto-fill: Gemini in JSON mode drafts exercises, workouts and whole programs; the coach can emit structured plans the client turns into real entities.
  • Social: public/private workouts and programs with likes and threaded comments.

Technical Architecture

Core Technologies

  • Next.js (App Router) with REST-style route handlers
  • Prisma + MongoDB for the data layer
  • NextAuth v5 with Google OAuth and credentials, using database sessions
  • Google Gemini (@google/genai) for the coach and auto-fill
  • TanStack React Query for client data, Zustand for local state
  • Tailwind CSS + Radix UI for the interface, Recharts for progress charts

One write, many consequences

Completing a session is the hub of the whole app. A single POST /api/workout-sessions fans out to goal progress, auto-progression and achievement evaluation, so every feature that depends on "you trained today" stays consistent without its own bookkeeping.

Exercise media without a foreign key

The exercise catalog (~6.3k entries, ~800KB) is generated from a CSV and kept server-only. A token-overlap matcher with equipment-aware tie-breaks finds the right clip for any exercise name — and deliberately returns nothing rather than a wrong clip when the match is weak. Clients batch-request media for a whole list through one hard-cached public endpoint.

Auth at the edge

Database sessions can't run Prisma in edge middleware, so route protection is split: a lightweight cookie check at the edge redirects signed-out users, while every API route still does a full auth() and ownership check.

Development Challenges

Making AI output useful

A chat reply is easy; a workout you can start is not. The coach is prompted with your owned workouts, logged sessions and goals, and responds with structured JSON that is validated and converted into real, editable entities.

Getting the numbers right

Streaks needed a single timezone-safe local-day helper, strength gain had to be a real average across exercises with enough history, and consistency is measured against the target you actually set — not a hardcoded number.

Technical Learnings

  • Modelling a domain around one well-defined write hub
  • Treating structured LLM output as an application primitive, with validation at the boundary
  • Where edge middleware ends and server auth must take over
  • Keeping large generated datasets on the server and shipping only what a screen needs

What's Next

  • Server-side search and sorting for community content
  • Moving the remaining useEffect fetches onto React Query
  • A shared, durable rate limiter for the AI coach