A daily deliberate-practice loop for frontend design. One focused drill per day, rendered, self-critiqued by vision, and logged. This page explains the rotation, the per-drill pipeline, and what you're looking at on each card.
The 8-step pipeline (runs every day)
Each drill follows the same fixed sequence. The only thing that varies day-to-day is which drill gets picked in step 1.
Load skill, pick drill. Read ~/.hermes/design-gym/log.md to see which category ran last, pick the next in the rotation.
Build. Write the drill as a self-contained HTML file with viewport meta + responsive CSS from the start.
Render both viewports. Desktop 1440×900 + mobile 390×844 via Playwright (snap.py).
Self-critique. Pass both PNGs to vision_analyze, score 7 dimensions on each viewport separately. Mobile-specific checks: no horizontal scroll, touch targets ≥44px, viewport meta present.
Iterate. Fix top 2-3 defects, re-render. Max 2 iterations.
Log. Append to ~/.hermes/design-gym/log.md with focus, score, key learning.
Publish. Copy HTML+PNG to this gallery, insert/update card.
Brand calibration cross-publish. If the drill was a brand clone, also publish to sketch.kurai.ltd.
The category rotation
Categories cycle in a fixed order so the practice doesn't over-index on what's fun (landing pages) and actually hits the weaknesses (filters, empty states, dense tables).
Thumbnails. Desktop (D) + mobile (M) side-by-side. Both viewports get rendered every day.
Score. 0–5 across 7 critique dimensions. Mobile and desktop scored independently.
Key learning. The single most important thing the critique caught — the compounding asset.
📋 badge. Indicates the drill prompt is available on the drill's own page. Click "View drill" → expand the "What was this drill?" panel in the top-right corner.
What's on the drill page (the 📋 panel)
Clicking through to a drill shows the actual build. With the 📋 badge, the page also includes a collapsible panel in the top-right corner with two blocks:
Drill
The verbatim one-line instruction from the skill's drill library. Same text every time that drill runs. Example:
Build a 12-column data table (monetary values, IDs, timestamps)
at 13px text, 10px cell padding, no gridlines, right-aligned numbers.
Target: Tufte data-ink ratio.
Interpretation
What the agent actually made of that instruction before building — domain picked, constraints added, aesthetic reference chosen. Generated fresh each run, so the same drill picked twice can produce two different interpretations. Example:
Building a SaaS analytics events table — Stripe-like event log.
Columns: timestamp, event_id, user_id, event_type, session_id...
Using tabular-nums on all numerics, aiming for ~18 visible rows,
Linear/Vercel dark aesthetic.
Why both? The drill line tells you what the menu said. The interpretation tells you how the agent read it today. Together they surface "the agent keeps picking safe domains" or "it never varies the aesthetic reference" — patterns you can't see from the build alone.
The drill library
The full menu of drills lives in the design-gym skill, grouped by category. The agent picks one per day from the current category. The library is intentionally small (~15 drills) so that each gets repeated and the log compounds across runs of the same drill.
Sample drills
Density: 12-col data table at 13px / 8 states of one component / collapsible sidebar at 240px and 48px
Typography: type-only hierarchy 6 levels deep / 6-metric numeric dashboard / orphan-widow control with text-wrap: pretty
Color restraint: pricing page with one accent only / dark-mode-native dashboard / colorblind-safe status semantics
Component craft: 5 empty states with what/why/next / ⌘K command palette with keyboard nav / faceted filter UI with URL-synced state
Reference matching: clone Linear / Stripe / Vercel against calibration memory
Anti-slop: redesign a generic SaaS landing / no-decoration page using only type+space+alignment
Failure modes (and how they're handled)
HTTP 429 from vision API. Critique step stalls. Cron surfaces a failure message (not silent) — reply "retry" to re-run.
Missing mobile render. Card publishes with desktop thumb only. Treated as a half-drill; flagged in the log.
Stale provider config. Cron refuses to run rather than silently using the wrong model. Re-pin and re-run.
Companion sites
sketch.kurai.ltd — brand calibration studies (the reference memory this gym draws on for "clone X" drills)