---
title: "Gym-Routine Grid — a typed routine → a TikTok-style colored-pencil grid of animated movements"
tier: hero
format: short-form-video
theme: fitness | how-to | sports | edutainment
persona: personal trainer, fitness creator, physio, gym brand, coaching app
duration: "1 routine → 9:16 grid reel (6/9 cells, or 12/18 doubled) in ~6–14 min"
budget_usd: "$0.50–$4.00 per reel (6–18 colored-pencil keyframes + ONE hyperframes-render board + music; +$ if you add real i2v motion)"
caps: ["generate_project", "gpt-image", "hyperframes-render", "ltx-i2v", "ltx-q-i2v", "ffmpeg-grid", "music", "sonilo-t2m", "ffmpeg-mux"]
skills: ["short-form-video", "hyperframes-overlays"]
showcases: ["/chapters/gym-routine-grid-example.html"]
status: "live (2026-06-12, v2 quality pass) — rendered E2E. The 'Push Day' showcase reel was produced via the PROVEN ACCURACY recipe: gpt-image clean instructional figures (side-profile, accurate form) → 3×3 grid → hyperframes overlay with numbered badges + directional rep-arrows + sets×reps + target-muscle → rep-tempo pulse + music. v1's colored-pencil pass read muddy/inaccurate at thumbnail; gpt-image + directive side-profile prompts is the fix."
reliability: 4.3 # 5 − colored-pencil consistency across 6–18 cells .4 − music .2 + .5 hyperframes-render does grid+overlay+animation in ONE deterministic pass (no per-cell i2v, no ffmpeg-grid dimension matching). The optional ltx-i2v motion path trades ~.5 reliability for real generative motion.
---

# Gym-Routine Grid — type a routine, get a one-screen animated movement board

Point this at any workout the user types — *"Push day: bench, incline DB press, weighted dip, cable fly, OHP, lateral raise, tricep pushdown"* — and it builds a **single-screen vertical (9:16) grid reel**: each cell is a short **colored-pencil, friendly hand-drawn animation** of one critical movement, all stitched into one TikTok-ready board, with a **stylish typography overlay** carrying the routine name and, per movement, its **strength** (load/intensity), **length** (sets × reps / time-under-tension), and **frequency** (×/week). The athlete is the user's choice — **male or female**. The bed is a **calm-but-energetic** instrumental that makes a movement board feel like a warm-up, not a lecture.

The visual rule that makes it feel good instead of clinical: **colored pencil, not CG.** A friendly hand-drawn athlete reads as encouraging and approachable; a photoreal or 3D body reads as intimidating and uncanny. So every keyframe is generated in a colored-pencil illustration style, and — because AI can never render legible text — **all the numbers (name, strength, length, frequency) live in a crisp HTML overlay**, never baked into a frame.

## ⭐ Quality recipe (PROVEN — the v2 accuracy fix)

The v1 "friendly colored-pencil" pass looked nice but **read muddy and drew movements inaccurately at thumbnail
size** — users couldn't tell what the exercise was. The fix that reaches reference-grade fitness-board quality:

1. **Model: `gpt-image`** (force it — set `wait_minutes:10` so the budget router doesn't downgrade to flux-dev).
   It follows instructional prompts and renders **accurate exercise form**; flux/recraft drift and distort anatomy.
2. **Style: clean instructional, not art.** Suffix: *"clean modern fitness exercise illustration, bold flat shapes,
   accurate anatomy, single figure on plain light background, instructional gym-diagram clarity, easy to read, no text"*
   (≤200 chars). Accurate + simple + effective beats "friendly but vague."
3. **Prompts: directive + SIDE-PROFILE.** Name the exact body position, equipment, and the key phase —
   *"side profile of an athlete on parallel dip bars, lowered with elbows bent ninety degrees, leaning slightly forward."*
   Side views read exercise form best.
4. **The standout = a `hyperframes` overlay** with, per cell: a **numbered badge**, a **directional rep-arrow**
   (↕ press / ↓ pushdown / ← pull / ↔ fly — the thing AI can't draw), and a chip with **sets×reps + target muscle**.
   Plus a clean title strip. This is what turns 9 figures into a save-worthy, professional workout board.
5. **Animation:** per-cell figure motion via `ltx-i2v`/`ltx-q-i2v` is the *premium* path — but the fal video tier is
   flaky (resolution-enum + "fetch failed" today). The reliable default is a **rep-tempo pulse** (gentle rhythmic
   zoom synced to a ~rep cadence) + the directional arrows, which conveys the movement without the i2v risk.
6. **Colored-pencil is still an option** (swap the style suffix) when "friendly over accurate" is the brief — but
   default to instructional when the user needs to *read the movement*.

> **NOTE:** gpt-image is slow (~140s/img) and a 9-scene `generate_project` can hit the 270s worker deadline — render
> in two passes or backfill stragglers with single `create_media` calls.

## What you'll get

> **A finished reel = vertical 9:16 (1080×1920) · a 6/9-cell (or doubled 12/18) grid of colored-pencil movements · per-cell stat labels + a routine title card · a calm-energetic music bed · 20–40s.** Generate one colored-pencil keyframe per movement with `gpt-image` (best hand-drawn fidelity — recraft drifts to generic kid-book, flux leans photoreal), then let **`hyperframes-render` build the entire board in one pass**: an HTML document that lays out the CSS grid, gives each cell a gentle colored-pencil-friendly animation (Ken-Burns drift / bob — the "small animation" needs nothing heavier), and renders the crisp title + per-cell stat chips on top. Then mux a ducked `music` / `sonilo-t2m` bed with `audio_fill:"loop"`. Because the cell motion is CSS, you don't need a per-cell i2v model at all — and if you *do* want real generative motion, use the **fast, reliable `ltx-i2v`**, never seedance (overkill for a thumbnail-sized clip). A grid where the reps are melted into a blurry frame, or the music cuts out, is a draft — the numbers live in the overlay, the bed covers every second.

## The two inputs the user gives you

```yaml
routine:        # free text, e.g. "Push day — bench, incline DB press, weighted dip,
                #   cable fly, overhead press, lateral raise, tricep pushdown"
athlete:        # "male" | "female"   (drives the figure in every keyframe prompt)
# optional:
cells:          # 6 | 9 (default 9) — one clip per movement
                #   OR 12 | 18 — TWO clips per movement (eccentric + concentric, or
                #   two angles), each 8–10s, for a denser/longer board
style_note:     # default "friendly colored-pencil"; user can nudge ("warm pastel", "marker sketch")
```

## Grid layouts (what "doubled" means)

| Cells | Layout | Clip plan | Per-clip | Best for |
|------|--------|-----------|----------|----------|
| **6** | 2×3 | 1 clip / movement | 3–5s | quick board, ≤6 lifts |
| **9** | 3×3 | 1 clip / movement | 3–5s | the default full routine |
| **12** | 3×4 | **2 clips / movement** ×6 | 8–10s | show eccentric **and** concentric phase, or 2 angles |
| **18** | 3×6 | **2 clips / movement** ×9 | 8–10s | the dense "every phase" board |

Doubling = each movement contributes **two** cells: clip A = the **eccentric / set-up** (lowering, stretch), clip B = the **concentric / finish** (drive, contraction). Adjacent cells in the grid, so the eye reads the full rep left→right. `ffmpeg-grid` tiles them in order; the overlay groups each pair under one stat chip.

## The cap chain — two paths (only live caps)

The key insight: **`hyperframes-render` (the HTML→video compositor) can build the whole board in one pass.**
It renders arbitrary HTML/CSS/JS over a background, so the *grid layout*, the *per-cell animation* (CSS Ken-Burns /
bob on the colored-pencil stills), AND the *typography* (title + stat chips) all live in one document and composite
deterministically. The movements here barely move — a gentle CSS drift sells it — so you don't need a per-cell i2v
model at all.

### Path A — hyperframes-render does it all (RECOMMENDED · deterministic · cheapest)

```
routine text + athlete (male|female)
  → agent parses the routine into N movements (6/9, or doubled to 12/18) and writes per-movement
       stats: STRENGTH (load/RPE), LENGTH (sets×reps / TUT), FREQUENCY (×/week), plus the routine NAME
  → generate_project                 # one colored-pencil keyframe per movement (square, 1:1)
       image: gpt-image              # ← hand-drawn colored-pencil fidelity (NOT recraft/flux)
       prompt: "colored pencil, friendly hand-drawn, soft paper texture, warm palette,
                a {male|female} athlete performing {movement}, single figure, no text"
  → hyperframes-render               # ONE HTML document → the entire animated board:
       • CSS grid (2×3 / 3×3 / 3×4 / 3×6), each cell an <img> of the keyframe
       • gentle CSS Ken-Burns/bob per cell  ← the "small animation", no i2v needed
       • title strip (NAME + athlete) + per-cell stat chip (move · strength · length · freq)
       • renders the whole 1080×1920 board to video in a single pass
  → music / sonilo-t2m               # CALM-ENERGETIC bed, ~90–110 BPM, warm, instrumental, loop
  → ffmpeg-mux                       # bed under the board, audio_fill:"loop" (covers every second)
```
No per-cell i2v, no `ffmpeg-grid` dimension-matching — one composite, pixel-perfect text, fully deterministic.

### Path B — real generative motion per cell (optional · when you want the figure to actually move)

```
  ... gpt-image keyframes →
  → ltx-i2v   (fast, reliable — the right call here; NOT seedance, which is overkill for a
               thumbnail-sized clip)  ·  or ltx-q-i2v for a touch more fidelity
       keep motion SMALL: a clean rep / phase, not a camera fly
  → then EITHER embed the resulting <video> cells into the hyperframes-render HTML grid
       (hyperframes composites videos + overlay in one pass — still one document),
    OR ffmpeg-grid the clips into the 9:16 board, then hyperframes-render the overlay on top
  → music / sonilo-t2m → ffmpeg-mux
```
Use Path B only when a still-with-CSS-motion isn't enough. For a 9-up board at thumbnail size, Path A usually looks
identical and never touches fal's flaky video tier.

## The typography overlay (the part AI can't draw)

The overlay is the deliverable's spine — it carries every number. One `hyperframes-render` HTML document, sized 1080×1920, composited over the finished grid:

- **Title strip (top):** the routine NAME in a friendly hand-lettered display face, the athlete tag (♀/♂), and a one-line summary (e.g. *"7 movements · ~45 min · 3×/week"*).
- **Per-cell stat chip (each cell's lower third):** `MOVEMENT` · **strength** (e.g. `RPE 8 · 70% 1RM`) · **length** (e.g. `4×8 · 3s eccentric`) · **frequency** (e.g. `2×/wk`). Semi-opaque warm card so it reads over any cell.
- **Style:** rounded, sticker-like chips with a soft pencil-stroke border to match the hand-drawn cells — the type feels drawn, not stamped.

Because the overlay is HTML, the numbers are always legible and editable — change a rep scheme and re-render only the overlay, not the clips.

## Male / female toggle

`athlete` is threaded into **every** keyframe prompt as the figure (`a {male|female} athlete performing …`). Keep the rest of the prompt identical so the colored-pencil style and composition stay consistent across the board. The overlay's athlete tag (♀/♂) flips to match. Nothing else changes — same grid, same stats, same music.

## Music: calm + energetic

A movement board wants a bed that is **calm enough to feel approachable, energetic enough to feel like momentum** — think warm acoustic/lo-fi with a steady pulse, ~90–110 BPM, no drops, no vocals.

```
music({ prompt: "calm but energetic instrumental, warm acoustic + soft electronic pulse,
                 ~100 BPM, motivational, no vocals, seamless loop", duration: <reel_len> })
# or sonilo-t2m for cleaner commercial licensing (brand/coaching-app deliverables)
```
Mux ducked under the board with `ffmpeg-mux` + `audio_fill:"loop"` so the bed covers every second of the grid.

## Quality bar (definition of done)

- ✅ All N cells are **colored-pencil / hand-drawn** — zero photoreal or CG figures.
- ✅ The athlete matches the chosen gender in every cell.
- ✅ Every cell has a **legible stat chip** (name · strength · length · frequency) — none baked into a frame.
- ✅ The routine **name** title card is present and crisp.
- ✅ The board is **one screen** (9:16, 1080×1920), cells tiled cleanly, no letterboxing.
- ✅ The music bed is calm-energetic, instrumental, and **covers the full duration** (no silent tail).
- ✅ For doubled grids: each movement's two phases are **adjacent** and read left→right.

## Watch-outs (cap ceilings)

- **Colored-pencil consistency across 6–18 cells:** `gpt-image` holds the style best, but re-state the FULL style preamble in every prompt (style drifts when abbreviated). Generate all keyframes in one `generate_project` call so they share the style suffix.
- **Prefer Path A — it sidesteps the flaky tier entirely.** CSS motion in `hyperframes-render` never calls fal's video models, so there's no "fetch failed" / latency risk and no `ffmpeg-grid` dimension-matching. Reach for i2v (Path B) only when you truly need the figure to move.
- **If you do use i2v, use `ltx-i2v`, not seedance.** seedance is a heavy cinematic model — overkill (and slower/pricier) for a thumbnail-sized cell. `ltx-i2v` is fast and reliable (its resolution bug is fixed); `ltx-q-i2v` if you want a touch more fidelity. Keep the motion SMALL — a clean rep, not a camera fly.
- **Text in the image is the #1 failure mode** — never let a frame carry the reps/load. The `hyperframes-render` overlay owns all type.
- **Colored-pencil cells in HTML:** give each `<img>` a soft paper-toned frame + a subtle CSS `transform` Ken-Burns so the still reads as gently alive; stagger the animation delays per cell so the board breathes instead of pulsing in lockstep.

## Execution mode (autopilot / director / auto)

This is a multi-scene project, so pass a `mode` to `generate_project` to control the **pre-finish gate** (after every cell renders, before the grid+overlay+mux): `autopilot` (the user is sure of the routine → ship in one call), `director` (pause to approve the colored-pencil keyframes before spending on motion + composite), or `auto` (recommended — ship UNLESS the critic flags a drifted/off-style cell). Setting `mode` runs the project async (returns a `job_id`); resume a pause with `review_checkpoint` + `resume_from_checkpoint` (`continue` to proceed / `abort` to discard). Director mode is especially worth it here: approve the 9 stills *before* paying for 9 i2v animations.
