From design-extractor
Render the canonical DESIGN.md brand document from extracted tokens, patterns, assets, voice analysis, and validation evidence — using the Jinja2 template and confidence-badged tables. Trigger on 'write a DESIGN.md'; 'format brand documentation'; 'produce the design doc for this extraction'; 'render the DESIGN.md from the cache'; 'generate the brand document'; 'compile the design system markdown'; 'write up the extraction as a DESIGN.md'; 'produce the per-brand design doc'; 'format the extracted tokens into markdown'. Do NOT trigger for: 'write project README', 'write a blog post about design', generic markdown writing, documentation for unrelated codebases, or design articles with no extraction artefacts to pull from.
How this skill is triggered — by the user, by Claude, or both
Slash command
/design-extractor:design-md-writerThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
- Phase C documentarian subagent is rendering the brand document at the end of an extraction
~/.claude/design-library/cache/<slug>/ and must become a single canonical markdown filedesign-system.html is being producedThe DESIGN.md is generated using a Jinja2 template at templates/DESIGN.md.jinja. The template receives a context dictionary with all extraction artefacts and renders a structured markdown document with confidence-badged tables, token evidence, and validation scores.
The rendered document has these sections in order:
Contains machine-readable metadata: brand name, slug, source URL, extraction date, extractor version, scores, confidence level, category tags. The frontmatter also serves as a skill definition file — when installed into a project's .claude/skills/ directory, Claude auto-loads the brand's design rules.
The brand name as an H1, followed by a prose summary paragraph. This paragraph gives a designer a quick feel for the brand's personality in 2-3 sentences.
A key-value table with: Industry, Category tags, Source URL, Extracted at, Source title, Theme colour, Has dark mode, Language variant. Any extra metadata fields are appended automatically.
The largest section, with subsections for each token category:
Table columns: Token | Value | Hex | Confidence | Source
Each row is one extracted colour. The hex column shows the colour value as a hex code. The confidence column shows the extraction confidence. The source column indicates where in the DOM the colour was found.
Below the table: brand impression paragraph, and a list of CSS custom properties if detected.
Table columns: Token | Value | Confidence
Contains font families, weights, and variations. Followed by a type scale table: Role | Size | rem | Source
Notable letter-spacing tokens and a typography narrative paragraph.
Table: Token | Value
Reports spacing.base and spacing.scale. Includes a narrative paragraph.
Table: Token | Value | Use
Each radius value with its intended use case and a narrative.
Table: Token | Value
Table: Token | Value | Use
Each shadow value with its use case.
Table: Token | Value | Label
Each transition value with its classification label (snappy/natural/luxurious).
List of breakpoint values extracted from media queries.
A dedicated section with deeper analysis: typography hierarchy table (Role | Size | Weight | Letter-spacing | Line-height), and a narrative paragraph about the type system.
Narrative about the spacing system, base unit, container max-width, and section padding values.
Per-component descriptions with optional HTML snippets. Components covered: nav, hero, button, card, footer, form. Each component has a prose description of its visual characteristics and an embedded code snippet showing the token usage.
The 15-signal pattern report table:
Table columns: # | Signal | Value | Confidence
All 15 signals are listed, even if some were not extracted (those show "(not extracted)" with LOW confidence). The 15 signals are:
Narrative about how the brand's design elements relate to each other (e.g., "the sharp radius language reinforces the authoritative navy-red colour system").
Tone spectrum table (Dimension | Position), list of defining traits, CTA patterns, language variant, do/don't microcopy table, and forbidden words list.
Motion label, median duration, and per-token transition listings with labels.
Table: Asset | Status
Tracks: Logo (light), Logo (dark), Favicon, Icon system, plus any extra assets.
Narrative about how well the extraction captures the brand's visual identity.
Tailwind config snippet, shadcn theme snippet, and the apply command for installing the brand into a project.
Gate scores table, iteration count, and final score from the validation pipeline.
Table: File | Origin
Lists each extraction artefact and the command that produced it.
Every token table uses three confidence levels:
| Badge | Meaning |
|---|---|
| HIGH | Extracted from multiple consistent DOM samples with high sample count |
| MEDIUM | Extracted but with limited samples or some inconsistency |
| LOW | Inferred or extracted from a single sample; needs verification |
Badges appear in the Confidence column of every token table. They are also aggregated into the overall confidence field in the frontmatter.
Collect from ~/.claude/design-library/cache/<slug>/:
tokens-output.json — extracted tokenspatterns.json — pattern signalsvoice-analysis.json — voice analysisreport.json — validation reportmetadata.json — brand metadataBuild a Python dictionary with these keys:
context = {
"brand": {
"slug": "westpac",
"name": "Westpac",
"source_url": "https://www.westpac.com.au",
"extracted_at": "2026-04-10",
"extractor_version": "0.1.0",
"language_variant": "en-AU",
"category": ["banking", "finance"],
},
"scores": {"overall": 0.95, "tokens": 0.92, "replica": 0.96, "voice": 0.88, "patterns": 0.93},
"confidence": "HIGH",
"extraction_method": "automated",
"at_a_glance": "Westpac is a major Australian bank...",
"metadata": {
"industry": "Banking",
"source_title": "Westpac Banking",
"theme_colour": "#DA1710",
"has_dark_mode": False,
},
"tokens": tokens_data,
"patterns": patterns_data,
"voice": voice_data,
"components": components_data,
"validation": validation_data,
"assets": assets_data,
"tailwind_config": "...",
"provenance": provenance_data,
}
from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader("templates/"))
template = env.get_template("DESIGN.md.jinja")
output = template.render(**context)
output_path = Path.home() / ".claude/design-library/brands/<slug>/DESIGN.md"
output_path.write_text(output)
Check that:
{{ }} or {% %})If the extraction is re-run or tokens are manually corrected, re-run the template with the updated context. The documentarian agent handles this automatically.
Each colour row should include:
Example:
| Token | Value | Hex | Confidence | Source |
|---|---|---|---|---|
colour.brand.primary | rgb(218, 23, 16) | #DA1710 | HIGH | 5 computed styles |
colour.brand.secondary | rgb(31, 28, 79) | #1F1C4F | HIGH | 3 computed styles |
colour.text.body | rgb(24, 27, 37) | #181B25 | HIGH | 12 computed styles |
colour.text.muted | rgb(87, 95, 101) | #575F65 | HIGH | 8 computed styles |
colour.border | rgb(222, 222, 225) | #DEDEE1 | MEDIUM | 2 computed styles |
Report both px and rem values, with the role derived from size context:
| Role | Size | rem | Source |
|---|---|---|---|
| hero heading | 72px | 4.5rem | h1.hero |
| section heading | 28px | 1.75rem | h2 |
| card heading | 20px | 1.25rem | h3 |
| body large | 18px | 1.125rem | p.subtitle |
| body | 16px | 1rem | p |
| small | 14px | 0.875rem | span, li |
| caption | 12px | 0.75rem | footer text |
| Token | Value |
|---|---|
spacing.base | 8px |
spacing.scale | 0, 4, 8, 12, 16, 24, 32, 48, 60, 90 |
spacing.container_max | 1280px |
spacing.section_padding | 48px |
The Jinja2 template at templates/DESIGN.md.jinja uses these patterns:
{% if tokens is defined and tokens.colours is defined %} — defensive checks for missing sections{% for c in tokens.colours.computed %} — iteration over token arrays{{ c.confidence | default('MEDIUM') }} — default filters for optional fields{{ tokens.spacing.scale | default([]) | join(', ') }} — list joining for spacing scales{% set signal_names = [...] %} — defining signal name lists for the patterns tableSee references/template-structure.md for the full section-by-section template guide.
references/template-structure.md — The DESIGN.md template section-by-section guidereferences/evidence-inlining.md — Where to place screenshots, scores, validation gates (planned)references/cross-links.md — Linking to tokens.json, SVG logo, design-system.html (planned)npx claudepluginhub imehr/design-extractor --plugin design-extractorCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.