skills/design-extract/SKILL.md
Extracts an OKLCH color palette, font families, and spacing heuristics from design references such as images, PDFs, URLs, and screenshots, and produces a draft DESIGN.md Front Matter report. Uses Vision MCP (fect-mcp__vision_analyze, vision_ocr) or WebFetch to analyze references. Inputs: local file paths, URLs, Figma screenshots, competitor sites, brand guideline PDFs. Output: docs/design-system/extract-report-{date}.md (a draft DESIGN.md Front Matter YAML + extraction evidence). This skill only generates the report — it never edits DESIGN.md directly. Merging is performed when the user, after reviewing the report, explicitly invokes /design-init --apply-extract=<report-path>. /design-init --from-refs=... also uses a one-way single-call flow where this skill is invoked once internally and the resulting report is merged.
npx skillsauth add astra-technology-company-limited/astra-methodology design-extractInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Analyzes design references such as images, PDFs, and URLs to extract OKLCH colors, fonts, and spacing tokens, and converts them into a draft DESIGN.md Front Matter.
This skill implements the "reference-anchored design" principle (vibe-coding-design-guide.md) in code. To avoid the generic look produced by AI coding, abstract descriptions ("modern·clean") must be replaced with concrete references converted into tokens. This skill automates that conversion.
The first positional argument of $ARGUMENTS is <paths-or-urls> (comma- or space-separated).
# Classify each input as one of four kinds
classify_input() {
local input="$1"
if [[ "$input" =~ ^https?:// ]]; then echo "url"
elif [[ -f "$input" && "$input" =~ \.(png|jpg|jpeg|webp)$ ]]; then echo "image"
elif [[ -f "$input" && "$input" =~ \.pdf$ ]]; then echo "pdf"
elif [[ -d "$input" ]]; then echo "directory"
else echo "unknown"; fi
}
Options:
--auto: handle all HITL with defaultsThis skill always generates the report only (v5.4.0+ one-way policy). Merging into DESIGN.md only happens when the user explicitly invokes
/design-init --apply-extract=<report-path>— to prevent a circular call (/design-extract ↔ /design-init).
Check whether Vision MCP is available:
# Check whether fect-mcp is registered in the Claude Code MCP server list
# If unavailable, fall back to heuristics (direct CSS/HTML parsing)
HAS_VISION_MCP=$(claude mcp list 2>/dev/null | grep -c "fect-mcp" || echo 0)
| Environment | Extraction accuracy | Response | |-------------|---------------------|----------| | Vision MCP available | High (dominant-color clustering, font estimation) | Use first | | WebFetch only | Medium (HTML/CSS parsing) | Handle URL inputs only | | Neither | Low (manual input required) | Ask the user to enter tokens directly |
mcp__fect-mcp__vision_analyze({
image_path: "{input}",
prompt: "Extract the following from this image: (1) 5-7 dominant colors as OKLCH. (2) 1-2 background/surface colors. (3) 1-2 accent colors. (4) Estimated font family (sans-serif/serif/mono). (5) Layout density (compact/comfortable/spacious). (6) Estimated border radius (sharp 0px / soft 4-8px / round 12-24px / pill). (7) Shadow usage intensity (none/subtle/medium/strong). Output as JSON."
})
Parse the response JSON to build an extraction-result dict.
Render the PDF pages as images, then apply Step 2A to each page. Brand guideline PDFs usually carry explicit color hex codes and font names, so use vision_ocr to extract text and regex-match:
mcp__fect-mcp__vision_ocr({ image_path: "{rendered_page}" })
#[0-9A-Fa-f]{6} → extract hex color → convert to oklch()font-family: ['"]?([A-Za-z\s]+)['"]? → font name# 1. Fetch HTML
WebFetch(url="{input}", prompt="From the head section of this page, extract link[rel=stylesheet] / style tag contents and brand color hex/rgb/oklch values and font-family used in body class names")
From the WebFetch result:
:root { --color-...: ... } CSS custom propertiesfont-family: ... declarationsbg-blue-600 / text-zinc-900If Chrome MCP is available, take screenshots and additionally apply Step 2A to improve accuracy.
Apply Step 2A to every .png/.jpg/.webp file in the directory. Gather dominant colors from multiple images and run frequency-based clustering (k=7).
Expand the extracted dominant colors (typically 5-7) into the ASTRA standard 11 steps (50~950).
Run the bundled conversion script (Ottosson OKLab algorithm, no external dependencies):
python3 "$CLAUDE_PLUGIN_ROOT/skills/design-extract/scripts/color-convert.py" "#3b82f6"
# → oklch(62.3% 0.188 259.8)
# Multiple colors at once
python3 "$CLAUDE_PLUGIN_ROOT/skills/design-extract/scripts/color-convert.py" "#3b82f6" "#10b981" "#f59e0b"
# stdin input
echo "#3b82f6" | python3 "$CLAUDE_PLUGIN_ROOT/skills/design-extract/scripts/color-convert.py" -
The output format follows the DESIGN.md Front Matter tokens.color.primitive.* convention (oklch(L% C H)). Pipe every extracted hex value through this script to guarantee consistency. If rgb()/rgba() input is needed, convert it to hex first, then call.
From the extracted colors, pick a Primary that satisfies all of:
chroma > 0.05)If multiple candidates exist, confirm with AskUserQuestion (in --auto, criterion #1 wins).
Keep the chosen Primary's hue·chroma and vary only the L value across 11 steps using the curve below:
shade L (%)
50 97.0
100 93.2
200 87.0
300 78.5
400 70.7
500 62.3 ← anchor (preserve the Primary color's chroma)
600 54.6
700 48.8
800 42.4
900 37.9
950 28.2
Reference the same lightness curve in $CLAUDE_PLUGIN_ROOT/skills/design-init/assets/color-palettes.yaml for consistency.
Map extracted font names to the ASTRA recommended font set:
| Extracted family pattern | Mapping | Note | |--------------------------|---------|------| | Geist, GeistSans, geist-sans | Geist | Direct match | | Inter, InterDisplay | Inter | Tailwind default | | Manrope, manrope | Manrope | Vercel style | | SF Pro, SFPro | -apple-system | Apple system | | Pretendard | Pretendard | Korean script default kept | | (Serif) Playfair, Lora, Merriweather | + serif accent | Activate Body §3 heading serif option | | (Mono) JetBrains, Fira Code, IBM Plex Mono | JetBrains Mono | code/data areas |
Organize the extraction result in the following form:
typography:
fonts:
sans: "{primary_sans}, Pretendard Variable, Pretendard, -apple-system, sans-serif"
mono: "{primary_mono}, ui-monospace, monospace"
heading: "{heading_font}" # if a separate heading font was detected
Convert the layout heuristics from image analysis into tokens as follows:
| Heuristic | spacing default | radius default | shadow usage | |-----------|-----------------|----------------|--------------| | compact | 4px base, button h=32px | sm (4px) | xs/sm only | | comfortable | 4px base, button h=40px | xl (12px) | md dominant | | spacious | 4px base, button h=44px | 2xl (16px) | lg/xl dominant | | sharp | — | none/sm | — | | pill | — | full | — |
Write the following to docs/design-system/extract-report-{YYYY-MM-DD}.md:
# Design Extract Report
## Source References
- {input 1 — kind · path · analysis timestamp}
- {input 2 — ...}
## Extracted Tokens (Front Matter draft)
\`\`\`yaml
brand:
inspired_by:
- "{reference 1}"
- "{reference 2}"
tokens:
color:
primitive:
primary:
50: ...
...
typography:
fonts:
sans: "..."
...
\`\`\`
## Detected Patterns
- Layout density: {compact|comfortable|spacious}
- Radius preference: {sharp|soft|round|pill}
- Shadow usage: {none|subtle|medium|strong}
- Iconography: {line|filled|emoji|mixed}
## Aesthetic Flags
- [ ] Purple→Blue gradient hero (anti-AI red flag)
- [ ] Generic shadcn default look
- [ ] Distinctive element detected: {e.g., serif accent in headings}
## Confidence
- Color extraction: {high|medium|low} (Primary identified from {n} candidate colors)
- Font extraction: {high|medium|low} (source: CSS / OCR / estimation)
- Density extraction: {high|medium|low}
## Next Step (user decision)
1. Review the report: `cat docs/design-system/extract-report-{date}.md`
2. To merge into DESIGN.md, explicitly invoke:
`/design-init --apply-extract=docs/design-system/extract-report-{date}.md`
3. To review only without merging, simply stop here.
This skill ends here — it does not auto-invoke
/design-init. One-way single-call principle (incorporates advisor feedback, v5.4.0).
| Input | Accuracy | Recommended use | |-------|----------|-----------------| | Brand guideline PDF (hex codes explicit) | ⭐⭐⭐⭐⭐ | Most accurate. Always use first | | Official design system site (e.g., stripe.com/design) | ⭐⭐⭐⭐ | Extract CSS custom properties directly | | Competitor UI screenshot | ⭐⭐⭐ | Dominant color accurate; fonts estimated | | Figma export image | ⭐⭐⭐ | spacing/radius derivable from grid analysis | | Photo or art reference | ⭐⭐ | Trust colors only. Ignore font/spacing |
/design-init's job. This skill only extracts and drafts.:root custom properties. Tailwind-class inference works as a secondary signal.tools
Runs UAT (User Acceptance Testing) cases in TRUE PARALLEL using Playwright Test runner with isolated browser contexts per worker (separate cookies, localStorage, sessionStorage). Solves the two main limits of /user-test: (1) sequential single-page execution that does not scale beyond a few cases, and (2) one stuck case blocking the rest of the run. Reuses 100% of the /user-test UAT case Markdown+YAML format under docs/tests/uat-cases/, runs them via `npx playwright test --workers=N`, and emits the same report layout (index.html + issues.md + session.json + screenshots/) under docs/tests/uat-reports/. Use when the user asks to "run UAT in parallel", "speed up UAT", "test multi-user", "song song", "uat parallel", or runs /uat-parallel. Distinct from /user-test (sequential Chrome MCP, supports interactive mode), /test-run (developer integration tests), /test-scenario (scenario authoring).
tools
Performs end-user UAT (User Acceptance Testing) by driving a real browser through Chrome MCP, self-verifying each step with hard assertions (DOM / Network / URL / Console), auto-assigning severity on failure, and emitting an HTML report plus issues.md into a timestamped session folder. Supports two modes: interactive (URL + Vietnamese natural-language flow description) and --auto (batch-run pre-authored test cases under docs/tests/uat-cases/). Use when the user asks for "UAT", "user acceptance test", "kiểm thử người dùng", "regression test", or runs /user-test, /uat. Distinct from /test-run (developer-authored technical integration testing) and /test-scenario (scenario authoring from blueprints).
tools
Authors and validates LLM tool descriptions and input schemas (Anthropic Tool Use, MCP servers, LangChain @tool, Pydantic, Zod). Use when the user mentions "tool description", "function calling", "MCP tool", "Pydantic schema", "Zod schema", "@tool decorator", "input_schema", "tool spec", "툴 정의", "함수 호출 스키마", or when editing files that define LLM tool surfaces. Enforces the six required attributes (one-line summary, anti-pattern, synonyms, parameter examples, enum constraints, return shape) and blocks the seven known failure modes — wrong-tool selection, skipped tool, malformed arguments, retry loops, user-intent bypass, wrong side-effect, and un-auditable traces. For authoring ASTRA SKILL.md files use /skill-author instead — this skill is for *runtime* LLM tool surfaces, not for skill files themselves.
development
Creates new SKILL.md files or refactors existing skills to comply with the ASTRA skill best practices guide (docs/development/skill-best-practices.md). Use when user mentions "new skill", "create skill", "SKILL.md", "skill authoring", "스킬 작성", "스킬 만들기", or when editing any file matching skills/**/SKILL.md.