DEV Community

Cover image for I built LiftCoach for Kavya, who lifted the same weight for months
Jo
Jo

Posted on

I built LiftCoach for Kavya, who lifted the same weight for months

Hacktoberfest Weekend Challenge: Build for a Friend Submission 🤝

This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend

What I Built

Kavya and I train at the same gym. She's consistent: she shows up, hits her sets, never skips. But for months she was stuck on the same weights.

She had no system for progressive overload. She didn't know when to add 2.5 kg, when to add reps, or when to deload.

So I built LiftCoach for her.

It's a simple tool that takes her recent weights and reps and applies the basic rules of progressive overload to tell her exactly what to do next session: add weight, add a rep, or hold. If she doesn't like an exercise, it suggests swaps that train the same muscles.

Demo

Code

GitHub logo jobs-code / liftcoach

Built for the Hacktoberfest 2026 Weekend Challenge

LiftCoach

A local, private workout progression coach. Enter your profile and your last sessions for the lifts you choose, and LiftCoach tells you the next weight, sets and reps. If you dislike a lift, it suggests swaps that train the same muscles.

Built for the Hacktoberfest 2026 Weekend Challenge: Build for a Friend. I built it for Kavya, who lifts same weight for months.

LiftCoach screenshot

How it works

Part Job
Python rules engine (logic.py) Decides next weight, reps and sets using double progression. Plain code.
Curated exercise table (logic.py) 20 exercises tagged by muscle group, movement pattern and equipment. Picks swaps for disliked lifts.
Gemma 3 4B via Ollama (app.py) An open weight model that only explains the plan in coach language. It never changes the numbers or adds exercises.
Gradio (app.py) The web form.

Safety checks: input range validation, plus a…

How I Built It

LiftCoach is split into two parts: plain Python for anything that has to be reliable, and an open-weight model for anything that needs language.

The stack

  • Python rules engine (logic.py) decides the next weight, sets and reps using double progression. If she hits 12 reps on every set, the weight goes up. If she hits 8 or more, she adds a rep. If she misses 8 reps two sessions in a row at the same weight, it deloads about 10%.
  • A curated exercise table of 20 exercises, each tagged by muscle group, movement pattern and equipment. When Kavya dislikes a lift, the code picks swaps from this table (bench press to dumbbell press, for example), so the swaps always hit the same muscles.
  • Gemma 3 4B through Ollama runs locally and only explains the plan in coach language. It never changes the numbers or adds exercises.
  • Gradio is the web form (the frontend).

Why I didn't let the model do the math. Small local models are unreliable at arithmetic, and a wrong weight jump is a safety problem. So the model gets the finished decision and only writes the explanation.

Safety and validation

  • Input ranges are checked (weight, reps, age, body weight), and bad entries get a clear message instead of a crash.
  • A body-weight sanity check flags logged weights far above the typical range for the user's body weight and gender. When it fires, the plan holds the weight until the input is confirmed. These ratios are rough heuristics from public strength-standard tables, not an official standard.
  • The under-18 supervision note is added by Python, not by the model.

What went wrong, and how I fixed it

  • Gemma invented a reason for disliking a lift ("you were feeling uncomfortable"). I added a prompt rule not to assume reasons.
  • It described the next target as if it had already been lifted. I told it the weights are next targets.
  • The warning said "double-check" but the plan still raised the weight. I made the plan hold the weight when an input is flagged.
  • Gemma added a supervision note for an adult. I moved that check into Python.
  • It called "same weight, add a rep" an increase. I added a prompt rule to describe the action exactly as given.

The lesson: the model drifts in small ways, so the exact plan is always shown first, generated by plain Python, and Gemma's text is only the explanation.

AI help: I used an AI assistant to help write the code, then tested it myself and adjusted the rules and prompts based on what I saw.

Why Does Open Innovation Matter?

LiftCoach asks for things people don't casually hand to a company: age, gender, body weight, and a full training log. Where that data goes is part of the product.

1. Privacy by design. Gemma runs on my Mac through Ollama, and the app sends nothing to a third-party server. I tested it offline and it still produced a plan. Users don't have to wonder whether their body data is being stored or used for ads.

2. It works where we train. Gym basements have bad signal. A local model doesn't care.

3. Free and durable. No API key, no per-request bill, no usage limit. A provider can't shut it down, reprice it, or change it under me.

4. Control over behaviour. Gemma drifted: it invented reasons, mislabelled actions, and added unsolicited advice. Because I controlled the whole stack, I could fix each problem myself: tighten the prompt, move the age check into Python, and keep the exact plan logic in plain code. I can also swap the model by changing one line.

Where it falls short: a 4B model on a laptop is slower and wordier than a large hosted model, and I had to work around its mistakes. Hosted APIs can be tuned too. For an app handling body data, I chose privacy and stability over raw capability.

Prize Categories

Best Use of Gemma.
LiftCoach runs Gemma 3 4B locally through Ollama. Gemma writes the coaching explanation, while plain Python rules decide the numbers and the swaps.

Top comments (0)