Open the starter file.
Edit exercises, loads, and schedule entries.
Validate the program before saving.
A small working program
The Designer starter is shown below as a minimal compiling example.
starter program
.is
// Tiny starter: one workout, one progressing lift.
program "Starter Squat" id="starter-squat" {
schedule = [A, rest, A, rest, A, rest, rest]
state {
squat_w = 60
}
workout A "Squat Day" {
exercise "Squat" {
count = 3
reps = 5
weight = squat_w
rest = 180
}
progress {
if all_complete {
squat_w = squat_w + 2.5
}
}
}
}Language guide
Core language pieces.
A program is composed from schedules, state, exercises, sets, config fields, templates, and progress rules.
Program identity and schedule
program "My Program" id="my-program" {
description = "One sentence summary."
about = """
*Bold* highlights, _italic_ nuance, simple lists, and numbered steps are
rendered in program detail views.
- Use `-` or `*` for bullets.
1. Use `1.` style markers for ordered steps.
"""
schedule = [dayA, rest, dayB, rest, dayA, rest, rest]
...
}idmust be unique across all programs. If omitted the parser uses the name.descriptionis the compact one-line summary for cards and lists.aboutis longer guidance for detail views. It remains a plain string in the
runtime, but web and mobile render a tiny Markdown-like subset: *bold*, _italic_, bullet lists starting with - or * , and ordered lists starting with 1. style markers.
scheduleis a weekly rotation: each entry is a workout id or the literalrest.- The scheduler advances
scheduleIndexcircularly;restentries are skipped automatically.
State
state {
squat_tm = 100
week = 1
}- All values are numbers (integers or decimals).
- State is mutable across sessions; config is immutable after enrollment.
- Every variable used in expressions must be declared here.
Exercises: shorthand vs. explicit sets
Shorthand (one block of identical sets):
exercise "Squat" {
count = 5
reps = 5
weight = squat_tm * 0.8
rest = 180
}Explicit (different sets within one exercise):
exercise "Squat" {
set { reps = 5 weight = squat_tm * 0.65 rest = 180 }
set { reps = 5 weight = squat_tm * 0.75 rest = 180 }
set { reps = 5 weight = squat_tm * 0.85 rest = 240 amrap = true }
}Set fields:
| Field | Type | Required | Notes |
|---|---|---|---|
count | number | no | How many identical repetitions of this set spec. Defaults to 1 when omitted. |
reps | number | yes | Target reps per set |
weight | number | no | Numeric load in the enrollment's active unit; concrete targets are rounded to the user's configured total-load jump |
rpe | number | no | Rate of perceived exertion, 1–10 |
rest | number | no | Rest period in seconds |
amrap | boolean | no | Last set is "as many reps as possible" |
warmup | boolean | no | Marks the set as warmup volume. Warmup sets are logged and displayed, but ignored by progress-rule completion checks. |
count may evaluate to 0 to omit a conditional set spec from the concrete workout. The legacy spelling sets is still accepted as an alias for count.
Config-driven exercises
name = ident in the body lets the user pick which exercise fills this slot at enrollment (the config value behind ident is an exercise reference id, not a display string). enabled = ident lets the user toggle the slot on/off.
exercise "T2 Squat" {
name = t2_squat_id
enabled = t2_squat_enabled
count = 3
reps = 10
weight = squat_tm * 0.5
}Progress rules
Triggered after each workout completion. All expressions evaluate against a snapshot of state taken before any updates in the block are applied. Order within the block does not matter.
progress {
if all_complete {
week = week < 4 ? week + 1 : 1
squat_tm = week == 4 ? squat_tm + 5 : squat_tm // sees old week, not the updated one
}
}Conditions:
all_complete: every set in the workout was completedany_complete: at least one set completedalways: fires unconditionallynot_all_complete: at least one set was skipped
When a progress block lives inside an exercise, it fires per exercise and sees bindings scoped to that exercise's logged sets (warmups excluded):
complete/incomplete: every work set was done (or skipped)amrapReps: reps logged on the final AMRAP settotal_reps: total reps completed across all work sets, regardless of weighttotal_volume: total weight × reps across completed work setstotal_time/amrapTime: seconds for timed setscompletedSets/numberOfSets: counts of done vs prescribed work setscompletedReps_N,targetReps_N,completedWeight_N, ... : 1-indexed per-set values
Array indexing for lookup tables
The [e0, e1, ...][idx] primary lets you build week/tier lookup tables inline. Index is clamped to bounds.
reps = [5, 3, 1, 5][week - 1]
weight = squat_tm * [0.85, 0.90, 0.95, 0.60][week - 1]Config block
Drives the enrollment onboarding form. Fields can seed state variables, be grouped into UI sections/slots, and be conditionally shown.
config {
squat_1rm: weight "Squat 1-Rep Max"
default = 100
-> squat_tm // seeds state.squat_tm at enrollment
reconfigurable // user can update after starting
use_accessory: boolean "Include accessory work?"
default = true
accessory_name: exercise "Accessory exercise"
if = use_accessory
optional
suggest = [dumbbell_row, cable_row_seated, machine_row] // catalog-id swaps shown first in the picker
scheme: select "Rep scheme"
default = "5/3/1"
option "5/3/1" { reps_target = 1 }
option "Boring But Big" { reps_target = 10 }
}Config field types:
| Type | UI widget | Notes |
|---|---|---|
exercise | Text/search input | Stores an exercise name string. Optional suggest = [catalog_id, ...] surfaces author-blessed swaps first (UI hint only; validated catalog slug ids) |
weight | Numeric input | Stored as number |
increment | Numeric input | Per-session weight increase |
boolean | Toggle | Stored as 0 (false) or 1 (true) in config |
select | Dropdown | Requires option declarations; can patch state |
Full-stack templates
Templates declare config fields, state variables, and exercises together. When expanded via use ... as "prefix", all identifiers are automatically prefixed. Weight/increment config fields implicitly seed state variables of the same name; no -> needed.
template t1(default_name, default_weight, default_inc) {
config {
name: exercise "T1 Exercise" default = default_name
tm: weight "Start Weight" default = default_weight
inc: increment "Increment" default = default_inc reconfigurable
}
state {
stage = 0
scheme_idx = 0
}
exercise "T1 Lift" {
name = name
count = [5, 6, 10][stage]
reps = [3, 2, 1][stage]
weight = tm
amrap = true
progress {
if complete { tm = tm + inc }
if incomplete { stage = stage < 2 ? stage + 1 : 0 }
}
}
}
workout A "Day A" {
use t1("Squat", 60, 5) as "A.t1"
}The as "A.t1" clause:
- Prefixes all identifiers:
tm->A_t1_tm,stage->A_t1_stage, etc. - Sets the config section for UI grouping.
- Template parameters (
default_name, etc.) are compile-time literal values substituted intodefault = ...clauses.
Starter workflow
Edit the starter in Designer.
A small, valid program you can edit, validate, and save, straight from the Designer.
Assistant workflow
Assistant context
Use the language guide and a close example when asking an assistant to draft or review IronScript.
Assistant guide
A compact file with the public IronScript reference, ready to paste into an assistant's context.
Open llms.txtDraft it in the Designer
Paste what the assistant writes into the Designer to compile it, see the projection, and fix anything that does not hold up.
Open the Designer