Build Fitbod
KINDAreplaces $15.99/mosaves $191.88/yrback to the verdict
A training planner whose interesting logic is progression under uncertainty: deciding what to lift next from what was actually lifted, tracking which muscle groups have recovered, and doing both inside caps that make a bug an inconvenience rather than an injury.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Runs the local application.
Get it nodejs.org, or nvm install 22. open ↗
Verify
node --version prints v22 or higher - decidefree
Why Both are enforced as constants before any progression runs, and deciding them after the logic exists means fitting them to the logic rather than to safety.
Get it Write down the maximum weekly load increase, the deload trigger, and which movements you will not program without stated coaching.
Verify
All three are written down and appear as constants in the safety module - have readyfree
Why Every generated plan is constrained by it, and the smallest available weight increment determines whether progression is even possible for a given lift.
Get it List what you have including the real weight increments, which for dumbbells is often much coarser than for a barbell.
Verify
The inventory includes the smallest increment per equipment type - have readyfree, and it takes eight weeks
Why Progression behaviour, recovery estimates and the failure and deload paths only become observable across weeks of real sessions with real missed reps.
Get it Log honestly, including the sessions that went badly, since those are the ones the logic is being tested on.
Verify
Eight weeks exist including at least three failed sessions - decidefree
Why The build stops and says to see someone qualified, and a message with nothing behind it is not much better than a suggested substitution.
Get it Write the message and decide what it points at, whether that is a professional body's directory or a specific instruction.
Verify
A written message exists and names a concrete next step
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- exercises(id, name, primary_muscles_json, secondary_muscles_json, equipment_required, technical_risk, requires_coaching) - equipment(id, kind, available, weight_increments_json) · what you actually have, including the smallest increment - sessions(id, planned_for, completed_at, perceived_effort, notes) - sets(id, session_id, exercise_id, ordinal, weight, reps, completed_reps, rpe, failed, pain_reported) - progressions(exercise_id, current_working_weight, last_increase_at, consecutive_successes, capped_by) - recovery(muscle, last_volume_at, volume_units, estimated_ready_at) - blocks(exercise_id, reason, from_at, cleared_at) · a movement stopped by pain, cleared only deliberately - A set records both prescribed and completed repetitions, because the difference between them is the entire input to progression.
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
DB_PATH | required | ~/.local/share/training/log.db | Training and pain reports. Health data, so treat backups accordingly. |
MAX_WEEKLY_INCREASE_PERCENT | required | 5 | A hard cap in the progression path. Not raisable at runtime. |
DELOAD_AFTER_FAILURES | required | 2 | Consecutive failures before load is reduced rather than held. |
PAIN_BLOCK_MIN_DAYS | required | 14 | Minimum before a pain block can be cleared, and only deliberately. |
SUGGEST_SUBSTITUTES_ON_PAIN | required | never | Present as a constant. Substitution requires knowing what is wrong. |
SESSION_TIME_BUDGET_MINUTES | required | 50 | Plans are generated to fit it, checked against real durations. |
The build, in order
Logging a session faster than resting between sets
Recording a set takes a couple of seconds while you are training.
Most sets go as planned. One action for the common case.
Files
src/logging.tsTheir difference is the whole input to progression.
Files
src/sets.tsNever read an abandoned session as failure.
Files
src/sessions.ts
done when · tick each as it passeswatch out- A logging flow requiring several taps per set gets abandoned mid-session, and a partially logged session is worse than an unlogged one because progression will read it as a failure and reduce the next prescription. Default to prescribed values, make completion one action, and mark abandoned sessions rather than treating them as data.
Progression with a ceiling on how fast
Load increases when earned and never faster than the cap.
Consecutive, recorded, in real increments your equipment has.
Files
src/progression.tsSo a logic error is an inconvenience rather than an injury.
Files
src/caps.tssrc/caps.test.tsHolding at a weight that keeps failing is not a plan.
Files
src/progression.ts
done when · tick each as it passeswatch out- Progression rules derived from repetition performance can compound quickly and prescribe a weight the person has never approached, and by the time it is obviously wrong they are already under the bar. Cap the weekly increase as a hard constant so a logic error produces a slightly wrong prescription rather than a dangerous one.
Pain stops the movement, not the plan
A reported pain removes that movement and does not get worked around.
Not reduce it, not substitute it. Block it.
Files
src/blocks.tsSubstitution requires knowing what is wrong, which the tool does not.
Files
src/blocks.tsBefore any other rule, so nothing can route around them.
Files
src/progression.tstests/pain-blocks.test.ts
done when · tick each as it passeswatch out- Offering a substitute exercise for a painful movement looks helpful and is the tool diagnosing something it cannot see, since the substitution depends entirely on what is actually wrong. Block the movement, say why, and suggest seeing someone rather than suggesting an alternative loaded exercise.
Knowing what is recovered
Today's plan avoids what you trained hard two days ago.
Simple, explicable, and honest about being an estimate.
Files
src/recovery.tsA percentage with no basis reads as a measurement.
Files
src/recovery-view.tsThey know about their sleep and their week. The model does not.
Files
src/recovery.ts
done when · tick each as it passeswatch out- Presenting a recovery percentage as though it were measured implies a precision that does not exist, since actual recovery depends on sleep, stress, nutrition and things the application cannot see. Show the estimate with what it was computed from, and let the user override it, since they know things the model does not.
A plan you can actually performproduct builder
Today's session fits your equipment, your time and your recovery.
Including the smallest increment. A plan you cannot load is not a plan.
Files
src/plan.tsMeasured against real session durations, not estimated ones.
Files
src/plan.tsUnless the user says they have been taught. Unsupervised risk differs by lift.
Files
src/plan.ts
done when · tick each as it passeswatch out- Generating a plan that ignores the equipment inventory produces sessions requiring a machine the person does not have, and they will substitute something arbitrary, which makes the progression data meaningless from that point on. Constrain generation by the declared inventory, including the smallest weight increment available.
That is the whole plan for Fitbod. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- Injury, form or technique assessment.
- Nutrition and body composition.
- Competitive lifting programmes.
- Video form checking.
- exercise library, adaptive programming, mobile capture, wearables, and coaching models
- wearable hardware data
- coach network
- clinical validation
- large content library and social network
- Exercise substitution within the same movement pattern for equipment reasons, which is a different question from pain
- Session history charts, which are motivating and honest since they show what happened
- Warm-up set generation, which is tedious to plan and easy to derive
Need the files? The project pack on the verdict page hands your agent the whole brief · more wellness.