OpenWodTimer encodes workout timers — EMOM, Tabata, AMRAP, For Time — into a single URL parameter that any app can parse.
OpenWodTimer defines a compact, human-readable, composable syntax for encoding any workout timer configuration in a URL. No backend needed. No proprietary formats. Just a query string.
An entire Tabata protocol fits in 27 characters. Share timers via QR code, text message, or hyperlink.
No UUIDs, no encoded blobs. Read the URL and instantly know it's a 10-round EMOM with 1-minute intervals.
Chain any workout types with mix(). Build competition formats, warm-ups, and complex training blocks.
HOW IT READS
Every common timer format, encoded in a function call.
Complete all work before the clock runs out. A countdown you race against.
As many rounds as possible in a fixed window. Push the pace, stack the rounds.
Every Minute On the Minute. Work at the top, rest whatever's left.
Alternating work and rest intervals. The protocol that changed HIIT forever.
Round Start At — explicit start times for each round. Perfect for wave starts and heats.
Chain any workout types together. Build competition formats and complex training blocks.
Four concepts. Zero complexity.
Six function names map to every common workout format.
ft()
amrap()
emom()
tabata()
rsa()
mix()
Times are MM:SS, counts are integers. That's it.
mix()Chain any types together. Nest as deep as 4 levels.
Append to any compatible app URL. The timer config travels with the link.
expression = workout
workout = ft | amrap | emom | tabata | rsa | mix | rest
ft = "ft(" time [ "," int ] ")"
amrap = "amrap(" time ")"
emom = "emom(" time "," int ")"
tabata = "tabata(" time "," time "," int ")"
rsa = "rsa(" time { "," time } ")"
rest = "rest(" time ")"
mix = "mix(" workout { "," workout } ")"
time = DIGIT DIGIT ":" DIGIT DIGIT
int = DIGIT { DIGIT } Build a timer URL, see it validated in real time.
Drop-in implementations for every major platform.
The specification is licensed under CC BY 4.0. All reference code is MIT. Fork it, extend it, build with it.