From grill-me-visual
Generate a single-file HTML questionnaire with side-by-side visual previews — UI mockups, CSS animations, Mermaid diagrams, font/typography samples, layout variations, code rendering comparisons — so the user picks from rendered options in the browser instead of describing choices in chat. Use for any visually-shaped design decision: layout, motion, typography, color, diagram shape, icon style, content rendering rules ("show me, don't tell me"). Useful for design reviews, design-system exploration, UI prototype direction, and surfacing ADR-worthy decisions. Ships with English and Chinese templates. Fire PROACTIVELY whenever you're about to ask the user 3+ visual-trade-off questions in chat, OR 2 questions where seeing options side-by-side would meaningfully change the answer — don't wait for them to ask.
How this skill is triggered — by the user, by Claude, or both
Slash command
/grill-me-visual:grill-me-visualThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Emits a **single-file HTML questionnaire** the user opens in a browser. Each question is a card in an accordion with rich visual previews. The user answers in the browser, clicks **Copy**, then pastes the markdown summary back into chat.
Emits a single-file HTML questionnaire the user opens in a browser. Each question is a card in an accordion with rich visual previews. The user answers in the browser, clicks Copy, then pastes the markdown summary back into chat.
Use this skill only when the decision space is visually-shaped — UI layout, motion, typography, color, diagram shape, or content rendering rules (how code / markdown / icons / math / tables get displayed). If the decisions are text only with no visual angle, ask them in plain chat instead — the HTML overhead isn't worth it.
Two templates ship with this skill — pick by user language:
| File | Use when |
|---|---|
template.en.html | The user writes English, or asks the questions in English. All chrome strings and the demo questions are English. |
template.zh.html | The user writes Chinese, or asks the questions in Chinese. All chrome strings and the demo questions are Chinese (Simplified). |
Both templates share identical CSS / JS / accordion / clipboard / Mermaid wiring — only the textual content differs. Mixing languages within one file works but reads poorly; pick one and stick to it for the round.
For other languages, copy the closest fit (probably template.en.html) and translate the chrome strings — see "Translating to a third language" below.
The template is a single HTML file (~1900 lines, ~75 KB, roughly 20–25k tokens — larger than the default Read window). Don't slurp the whole file. Use these patterns:
Bash grep -n "PATTERN:" lists what pattern each demo card uses. Delete the cards for patterns you don't need (whole <!-- QN START -->…<!-- QN END --> block) sight-unseen — no Read.grep -n "Qn START" to locate, then Read with offset + limit (~80 lines per card)Edit that block in one call without reading the rest of the fileDo not rewrite the template — copy it and edit only the question content.
1. Bash: mkdir -p .grill-me-visual && cp <skill-dir>/template.<en|zh>.html <output-path>
# <skill-dir> = the directory this SKILL.md lives in. Resolve from the
# path the harness gave you when loading the skill.
# <output-path> = .grill-me-visual/grill-{topic-slug}-round-{N}.html
# — hidden top-level folder in the user's CWD (dot prefix keeps it out
# of `ls` output and avoids colliding with the skill's own source dir
# when running inside this repo). Decisions belong to the project
# they're about; multi-round files cluster together; the user can
# commit them or gitignore them at their own discretion.
# Use a relative path with forward slashes so it works cross-platform
# (macOS, Linux, WSL, Git Bash, PowerShell, cmd). Avoid `/tmp`
# (missing on native Windows) and `mktemp -t ...` (semantics differ
# between macOS and Linux).
2. Bash: grep -n "PATTERN:" <file> # which Qn uses which pattern
Delete whole QN blocks for any pattern you're NOT using (markers and
all) — no Read needed. Renumber survivors' `data-id` sequential q1…qN.
3. Edit: replace `const TOPIC = "..."` with this round's topic
4. Edit: replace `const ROUND = ...` if this is round N > 1
5. Edit: replace masthead `<span class="topic">...</span>` text to match TOPIC
6. Edit: replace the `<p class="lede">...</p>` with a roadmap-style POV sentence
7. Edit × N cards: replace each surviving card body between its
`<!-- ─────────── Qn START · PATTERN: ... ───────────` and
`<!-- ─────────── Qn END ─────────── -->` markers.
Card IDs go q1, q2, … qN; the markdown output groups answers by this id.
8. Sanity check BEFORE handing off. If you have browser access (Chrome MCP,
Playwright, headless browser, etc.), open the file and verify Mermaid
renders, fonts load, and layout holds. Always also grep-check structure:
- `grep -c 'data-id="q' <file>` matches your intended card count (and IDs are q1…qN sequential)
- `grep -c '<button[^>]*data-rec="1"' <file>` == card count — every question has exactly one recommended option
- `data-value="..."` slugs are unique within each card
Without browser access, also eyeball-check from source:
- Mermaid `<pre class="mermaid">` blocks against the hard constraints (no `:`, no `"`, no `<`/`>`, basic shapes only)
- Every `font-family` referenced is loaded via the Google Fonts <link> in <head>
9. Hand off. Best-effort: launch the file in the user's default browser (skip
silently if headless / no GUI). Then output ONE clickable markdown
link from the user's CWD — `[<filename>](<relative-path>)` — as the
re-open handle. No absolute path, no separate command line. If the
user reports a Mermaid / font / layout issue, fix and re-hand.
Do not touch:
<head> (CSS, Google Fonts, viewport meta, theme-color, copy fallback are pre-wired). Exception: when translating, swap CDN URLs if needed.<script> block at the bottom (Mermaid init, accordion logic, copy/reset, dirty-flag tracking, mobile-safe clipboard fallback, tag-rec auto-inject). Exception: when translating, edit the LANG = { ... } object at the top of <script> and nothing else — see "Translating to a third language" below..card / .opt / .opt-tags / .chevron / scrollbars / dark mode--paper, --ink, --clay, --moss, etc.)If you find yourself wanting to change CSS/JS, stop and ask the user — the template already handles mobile-safe copy, font fallback (incl. Chinese), dark-mode contrast, Mermaid theming, and small-screen layout.
Each card replaces the block between <!-- Qn START --> and <!-- Qn END -->. Open Q1 in the template for the canonical structure — copy it and substitute your content. Required slots (in order):
data-id="qN" on the wrapping <div class="card"> (must match position in 1–N sequence)<span class="qnum">Qn.</span> and <span class="title-text"> in .card-header<p class="q-desc"> — what / why (Setting → impact). No option preview here.<p class="rec-hint"><b>{name}</b> — {one-line why}</p> — recommendation reasoning<button class="opt opt-rich" data-value="slug" [data-rec="1"] data-label="A. …"> preset options with .opt-preview + .pros-cons + .opt-label. Letters A, B, C, … sequential; exactly one option has data-rec="1". Use as many as the decision genuinely has — if you can't find 2, ask in chat instead; if you'd need 5+, consider splitting into two questions.<div class="opt opt-input"> for free-text "Other…" — always last, letter following the last preset.Tags: set <span class="opt-tags"><span class="opt-tag tag-current">Current</span></span> on the option the user is using today (if any). The Recommended tag is auto-injected from data-rec="1" — don't add it by hand. To translate the recommended label, edit LANG.tagRec only.
Pick ONE pattern per question. All preset options within one question MUST use the same pattern.
| Pattern | Demo card | Use when |
|---|---|---|
| #1 UI mockup | Q1 in template | "how it should look" — layout / container / render style |
| #2 CSS animation | Q2 in template | motion — loading, streaming, transition |
| #3 Mermaid | Q3 in template | shape of a flow / state / sequence |
| #4 Font | Q4 in template | typography — body, wordmark, display |
| #5 Code snippet | Q5 in template | content comparison — same default rendering, different content |
| #6 Text-only | Q6 in template | no genuine visual angle (last resort) |
Open template.en.html or template.zh.html and read the matching demo card as the canonical structure to copy from. If none of these 6 fit, invent your own pattern — the preview HTML/CSS goes inside .opt-preview; keep the rest of the card structure unchanged. Add a <!-- PATTERN: ... --> comment so the next round can spot it.
Use this when the decision is "how the UI should look" — different layouts, container styles, render styles for the same content. Use real placeholder copy at microscale (~60–70% of real proportions), not gray-bar wireframes (those look like skeleton loaders).
@keyframes)Use this when the decision is about motion — what to show while loading / streaming / transitioning. Animations render inline so the user actually sees them move.
The template predefines reusable keyframes in its <style> block (demo-cursor-blink, demo-dots, demo-fade-token). Reuse those for cursor / dots / fade patterns rather than defining new ones; only add new @keyframes if you need a different motion.
Use this for "process / state / control flow" decisions where the comparison is shape of the flow. Drop a <pre class="mermaid">…</pre> inside each option's .opt-preview.
Hard constraints (the template's Mermaid renderer assumes basic shapes only):
[Send] not ["Send"]A[Send · message] or A[Send — message], not A[Send: message]< / < / > in labels — they don't decode. Reword the condition: write D{Can retry?} not D{Retries < N?}id[text] id{text}. No stadium ([..]), hexagon {{..}}, parallelogram >..], asymmetric >..]flowchart TD / LR, sequenceDiagram, stateDiagram-v2, erDiagram, or classDiagram — the themed CSS overrides target these%%{init: ...}%%), classDef, or inline style statements — they collide with the brand palette overrides; let the template's defaults renderUse this for typography decisions — body system, wordmark, display headline, etc.
Important: if any candidate is a Latin-only font (Source Serif 4, Inter Tight, Geist, etc.), the differences only show on Latin characters — non-Latin scripts (Chinese, Japanese, etc.) fall back to the system font on every option. If the user is comparing for a CJK product and you want the difference to read in mixed Latin + CJK, use a mixed sample explicitly.
Mandatory: load every candidate font. Referencing font-family: 'Geist' in an inline style without loading it = silent fallback to system, and the comparison is broken.
The template's <head> already loads: Source Serif 4 (serif display/body), Manrope (sans), Noto Sans SC + Noto Serif SC (Chinese fallbacks). To add more, append &family=<Name>:<spec> to the Google Fonts <link> URL — copy the spec from fonts.google.com (spaces become +).
Use this when the decision is about the content of code — competing data shapes, algorithms, API signatures, prompt formats, config schemas — and each option is a small snippet of code with the same look.
The template provides a .code-snippet component for the default rendering — header with language tag, then a syntax-highlighted <pre> body. Drop it inside each option's .opt-preview:
<div class="code-snippet">
<div class="code-head"><span class="code-lang">typescript</span></div>
<pre><span class="tok-kw">const</span> x = <span class="tok-num">1</span>;</pre>
</div>
Optional highlight token classes: .tok-kw (keyword), .tok-id (identifier), .tok-str (string), .tok-num (number), .tok-cmt (comment). Plain text inside <pre> is fine — highlighting is decorative.
If the decision is instead about how content should be rendered (line numbers vs syntax highlight for code, table style for tabular data, emoji vs SVG for icons, KaTeX vs MathJax for math, etc.), that's a UI mockup question (pattern #1), not a content-snippet question — the "UI" you're comparing is the rendering component itself.
For decisions with no visual angle (e.g. "should the AI greet the user proactively?"), use opt-rich but put only <ul class="pros-cons"> inside .opt-preview — no visual mockup. The "all-or-none preview" rule means ALL options in this question must be text-only.
For genuinely open-ended questions where some options have "no UI" (e.g. silent greeting = blank screen), use a plain .opt with no opt-rich:
<button type="button" class="opt" data-value="none" data-label="A. None">
<span class="key">A.</span>None (stay with current)
</button>
<b>{option name}</b> — {reason it beats the other choices}. Don't just restate the recommended option's pros — those go in its pros-cons list. rec-hint answers "why this one and not the others"; pros-cons answers "what are the trade-offs of this specific option in isolation".<ul class="pros-cons"> with 2–3 <li class="pro"> and 1–2 <li class="con">. Pros first, then cons. Exception: pure-affordance options like "None" in nullable questions..opt-preview mockup, or none does. Pattern #6 (text-only) is the all-none case: every option's .opt-preview holds only pros/cons, no mockup. Don't mix mocked options with plain .opt (no opt-rich) options in the same question.data-rec="1" — that single attribute drives both the (recommended) suffix in the markdown output and the auto-injected Recommended tag in the UI. Don't write the tag span by hand.tag-current is manual, tag-rec is automatic. Add <span class="opt-tag tag-current">Current</span> inside <span class="opt-tags">…</span> when the user is doing this thing today. The recommended tag appears automatically wherever data-rec="1" is set — see rule 5.The two shipped templates are kept structurally identical — their <script> bodies are byte-identical after the LANG object — and differ in exactly two places:
LANG = { ... } object at the top of <script> — all strings that JS emits dynamically (markdown output, button states, warning text, the Recommended tag label).tag-current label, every demo card's body.To add a new language: copy whichever template is closest, swap (1)+(2), and diff the JS body against the original to confirm nothing else drifted. Run diff <(awk '/^const dark = matchMedia/,/^<\/script>/' template.en.html) <(awk '/^const dark = matchMedia/,/^<\/script>/' template.NEW.html) — it must be empty.
Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
npx claudepluginhub akiyax/skills --plugin grill-me-visual