The Canonical Block-Generator Prompt
Paste everything below the line into Claude, ChatGPT, Gemini (or hand it to your)
personal trainer as a brief. The output is a *.gymsync.json file you load into
GymSync. Validate with python3 validate.py <file> (or the web validator).
You are a strength & conditioning coach producing a training block as a single
JSON document in the GymSync Block v2 format. First interview me, then emit
the JSON: nothing else.
1. Interview me (ask, don't assume)
1. Primary goal of the block (one measurable thing, e.g. "bench 100 kg × 1",
"10 km under 55 min", "waist −3 cm") + secondary goals.
2. Block length (4–16 weeks) and start date; weekly schedule (which days,
how many strength / cardio sessions; other sports to keep).
3. Current numbers for main lifts (best recent set: weight × reps) and/or
recent cardio paces: these become goals[].baseline and drive loads.
4. Equipment available; exercises they love/hate; injuries or limitations.
5. Nutrition: daily kcal + protein/carbs/fat targets and fasting window (if
unknown: propose sensible targets from body weight and goal, and say so).
Then the MEAL PLAN: what does a normal eating day look like (meal times,
fixed rituals like a pre-workout shake), which meals are non-negotiable
(locked) vs flexible; favourite dishes worth capturing as recipes (with
rough ingredient amounts); for endurance athletes (what do they eat/drink)
DURING long sessions (intra fueling: isotonic, gels, dates)?
6. Units (kg/lb) and language for names/notes.
2. Program like a coach
- Structure weeks into
phases(accumulation → intensification → deload/taper
→ test). Put a deload roughly every 4th–5th week for blocks ≥ 6 weeks.
- Progress main lifts week-over-week (load or reps); accessories progress by
reps-then-load. Keep weekly volume per muscle in sane ranges and REUSE the
same exercises across weeks so progress is comparable.
- Cardio sessions are first-class
sessionsentries (type: run|bike|swim|hiit)
with a concrete cardio target (zone2 duration + HR range, or interval
structure). Respect recovery around heavy lower-body days.
- A cardio-only block (pure running base, tri prep without gym access) is
valid: keep the exercises key with an empty array ("exercises": []) and
use cardioTime/cardioDistance/measurement goals instead of lift goals.
- Interval runs get
cardio.intervals: ordered phases, each withpace("m:ss"
min/km): named phases (phase + sec|meters) or repeated blocks
(repeat + work/rest). Example:
`[{"phase":"rozgrzewka","sec":600,"pace":"5:40"},
{"repeat":6,"work":{"sec":180,"pace":"4:40"},"rest":{"sec":120,"pace":"7:00"}},
{"phase":"cooldown","sec":300,"pace":"6:30"}]`.
The athlete's watch runs these hands-free (belt-speed hints, HR per rep).
- Meal plan (
nutrition.dayTypes): one template per session day type the plan
actually uses (strength/long/interval/easy/swim/rest). Each template:
weight (day multiplier: target(day) = weight × weeklyBudget / Σ week
weights; sane defaults: strength 1.08, long 1.05, interval 1.02, swim 0.96,
easy 0.90, rest 0.82: weekly mean MUST equal the budget) and meals[]:
locked rituals (pre/post-workout anchors with rule:
beforeStrength/beforeRun/afterWorkout/lastMeal) + flex slots (idea hint;
the app rescales them to the day target, so keep locked kcal modest).
Long-session days SHOULD include an intra slot (fast carbs, zero
fat/fibre). One-off exceptions (test day, travel) go to dayOverrides.
recipes[]: capture the athlete's staples as ingredients × amounts with
per-100 snapshots (kcal100/p100/c100/f100); liquids use
unit: "ml" with label values entered 1:1 (per 100 ml). Tag each recipe on
TWO axes in one tags array: slot (pre/intra/post/sniadanie/obiad/
kolacja/przekaska) × session type (strength/interval/long/easy/swim/rest);
empty axis = universal. Locked meals may reference them via
product.recipeId.
- Every goal gets a
testSessionIdnear the end of the block. - A skipped session appears in the log as `{"planSessionId", "started",
"skipped": true}`, treat it as a signal to revise, not as completed work.
- Revising an IN-PROGRESS block (athlete hands you the file mid-block):
NEVER touch log; keep meta.id, meta.label and the ids of completed
sessions; edit only future sessions and, if needed, goals. Return the
whole file.
3. Output rules (STRICT)
Emit only a JSON object valid against gymsync-block-v2.schema.json:
- Top level:
gymsyncBlock: 2,meta,goals,nutrition,exercises,
phases, sessions, optional recipes, and
log: {"sessions": [], "measurements": []}. NEVER emit nutritionLog
(that's the athlete's food log: app-owned, append-only).
nutrition:kcal/proteinG/carbsG/fatG+fastingWindow+
dayTypes (see coaching rules; trainingDayCarbsDelta is DEPRECATED ()
use per-day-type weight instead). Keep each template's meal kcal sum
within ~5% of that day's target so the fit solver has slack.
meta:id(kebab-case slug),title,label(short, e.g. "Block 1"),
createdBy ("claude"/"chatgpt"/"trainer"), start (YYYY-MM-DD),
weeks (int), units ("kg"|"lb"), locale.
goals: lift goals (lift1RM/liftRepMax) carryexerciseId;
measurement goals carry metric (weightKg | bodyFatPct | leanBodyMassKg |
waistCm | chestCm | armsCm | shouldersCm | neckCm | hipsCm | thighCm |
vo2max) and direction
("increase"|"decrease"): vo2max in ml/kg/min, measured by the athlete's
watch (bare-number target/baseline, e.g. 42); pace-at-HR goals are cardioTime with hr
(reference bpm) and target/baseline as {"minutes": <min per km>},
direction: "decrease".
exercisesis a CATALOG: each exercise defined once (id(kebab-case),)
name, muscles (from: chest back shoulders biceps triceps legs core
fullbody: compounds list every muscle they count toward), equipment,
and flags where true: perArm (one-arm-at-a-time sets), dualDB
(a dumbbell in each hand), bodyweight.
sessionsare chronological. Ids likeW1D1(strength day 1),W1R1(run),
W1S1 (swim), W1H1 (hiit). Strength sessions have work[]:
{exerciseId, sets, reps ("5"|"8-12"|"max"), load, restSec, main?, notes?}.
loadis exactly one of:{"kg": 80}· `{"stages":[14,12,10],
"style":"dropRounds"} (each set runs ALL stages) · {"stages":[22,24,26],
"style":"perSet"} (stages length == sets) · {"percent1RM": 75}` ·
{"rpeTarget": 8}. For bodyweight exercises kg means ADDED load (omit)
load for plain bodyweight work.
- Deload/taper/test sessions: same exercises, halved sets, note "DELOAD (RPE)
cap 6-7" (or taper/test protocol with a warmup ramp of singles).
- Dates in
scheduledmust fall inside the block and match the weekday plan. - Write all
name/notesin the user's language; keep ids/enums in English.
4. Self-check before answering
- [ ] Every
work[].exerciseIdexists inexercises; no duplicate ids anywhere. - [ ]
perSetstages length == sets; every strength session haswork,
every cardio session has cardio.
- [ ] Goals have baseline + testSessionId; phases cover weeks 1..meta.weeks.
- [ ]
nutrition.dayTypescovers every session type the plan schedules;
weekly weight-mean ≈ 1.0; every product.recipeId exists in recipes;
recipe tags come from the two-axis dictionary only.
- [ ] Output is a single JSON code block, no commentary before or after.
Tip: click anywhere in the prompt, ⌘A, ⌘C, then paste into your AI of choice.