Design System From Reference — Skill (v0.2)
What you (Claude) actually do
You are a multimodal model running inside Claude Code. When you Read a PNG
file, you see the image. This skill exploits that: the harvest script
dumps a dozen small focused screenshots (rest+hover buttons, individual
headings, individual cards, hero crop, nav strip) instead of one giant
full-page PNG. You read those small images one at a time, describe what
you see in design-token terms, and use the JSON files alongside only for
exact numeric values.
This is the whole point of v0.2: the previous version tried to grep compiled CSS, which only works on Tier 1 sites. Looking at pixels works on any site whose buttons are made of pixels.
When invoked
User typed /design-system-from <url> or asked you to follow this skill
with a reference URL. They expect:
- A tier classification with honest expectations.
- A
design.mdpopulated with REAL values from the harvest. - A minimal
ds/folder +/design-testsandbox. - A "Frontend Design System" section appended to
CLAUDE.md. - A summary of what was harvested, what's high-confidence vs guessed.
If no URL — ask for one. Without calibration the output is generic AI aesthetic, which defeats the point.
Workflow
Step 0 — Locate the bundle
This SKILL.md ships next to capture.mjs and templates/. Find the bundle
absolute path. Common locations: ~/tools/design-system-starter/,
~/.claude/skills/design-system-starter/, ~/dev/design-system-starter/,
/tmp/dss/ (one-prompt zero-install path).
If not found in defaults — ask the user.
Step 1 — Run the harvest
cd "$BUNDLE_DIR"
[ ! -d node_modules ] && npm install
[ ! -d ~/.cache/ms-playwright ] && npx playwright install chromium
TARGET=<user-url> node capture.mjs
Output lands in /tmp/<sitename>-extract/. Manifest:
| File | What it gives you |
|---|---|
01-full-desktop.png | Full page. Do not Read — usually >5MB, will blow context. |
02-fold-desktop.png | Above-the-fold. Always Read first. This is the design's first impression. |
02a-nav.png | Nav strip alone. Read if you need nav recipes. |
02b-hero.png | Hero section crop. Read to understand h1 treatment. |
03-full-mobile.png | Mobile fold. Read for responsive sanity. |
btn-<name>-rest.png + btn-<name>-hover.png | Buttons in both states. Read pairs side-by-side to describe hover delta. |
btn-<name>.json | Exact computed values at rest + hover. Numbers to back up what you see. |
heading-h1-0.png, heading-h2-0.png, ... | Individual heading crops. Read to detect gradient text. |
big-text-styles.json | Typography numbers per heading. Critical field: webkitTextFillColor: rgba(0,0,0,0) + backgroundImage: ...radial-gradient... → h1 painted via background-clip:text. |
card-N.png | Top 3 card-shaped elements. Read to describe card treatments. |
cards-inventory.json | Card numbers (bg, border, radius, shadow, backdrop-filter). |
buttons-inventory.json | Computed styles of every interactive element on page. |
tier-hints.json | Cheap signals to classify site tier. Read this BEFORE anything else. |
network-requests.txt | Runtimes loaded: @rive-app, framer-motion, gsap, lottie, etc. |
Step 2 — Tier classification (do this before extraction)
Read tier-hints.json. Apply this rubric to classify the site:
canvas_area_ratio > 0.5 → Tier 4 (Canvas-heavy)
hashed_classes > total_classes * 0.5 → Tier 3 (CSS-in-JS)
tailwind_like_classes > total_classes * 0.3
AND custom_props_in_html < 20 → Tier 2 (Tailwind utility)
custom_props_in_html > 30
OR semantic_classes > 20 → Tier 1 (Semantic CSS / design tokens)
otherwise → Tier 2 (default)
Report the tier to the user with honest expectations:
| Tier | What works | What you should warn about |
|---|---|---|
| 1 (semantic CSS) | Everything. Tokens, hover deltas, gradient text — all recoverable. | Nothing major. Proceed. |
| 2 (Tailwind) | Computed values reliable. Hover deltas reliable. | Token names will be inferred (you decide what's "primary" vs "secondary" by looking). |
| 3 (CSS-in-JS) | Computed values reliable. Visual reasoning works. | Token names invented. No way to follow upstream changes — frozen snapshot. |
| 4 (Canvas/WebGL) | Static look only. | Interactivity not harvestable. Tell user honestly: "I can mimic the look, not the motion." |
| 5 (adversarial / private) | Nothing reliable. | Refuse with explanation. Suggest user share screenshots manually instead. |
For Tier 4/5: stop here. Tell the user what you found and offer alternatives (e.g. "share a screenshot of the page section you want and I'll extract from that").
Step 3 — Vision-first extraction
This is the heart of the skill. You are a multimodal model. Read the small focused PNGs, describe what you see, then use JSON for exact numbers. Don't try to grep tokens out of compiled CSS — that approach falls apart on Tailwind, CSS-in-JS, and canvas-driven sites. Looking at pixels works on anything visible.
3a — First impression (sets the vibe)
Read 02-fold-desktop.png. In your head, answer:
- Is the canvas dark or light?
- Are there ambient gradients/auras on the background, or flat?
- Typography weight — heavy or thin?
- Density — generous whitespace or compact?
- Mood — editorial, technical, playful, brutalist?
These adjectives drive token defaults for everything below.
3b — Buttons (run for every btn-*-rest.png you have)
For each named button:
Read btn-<name>-rest.pngANDbtn-<name>-hover.png(both, side by side mentally).- Describe the hover delta in plain English: "background lightens", "shadow shifts down 2px", "border brightens by ~30%", "no visible change" — whatever you actually see.
Read btn-<name>.jsonfor the exact numeric values backing your observation.- Categorize: is this a primary CTA (filled / accented), an outline secondary, or a header/ghost tertiary? Use both size and prominence signals.
Pick the single most prominent button as accent-cta in your design.md. Pick the next as outline. Pick the smallest/quietest as ghost.
3c — Typography (run for every heading-*.png)
For each heading screenshot:
Read heading-<tag>-N.png.- Visually: is the text plain colored or gradient-painted? (Gradient-painted = different colors blending within letterforms, often pastel halos.)
- Read
big-text-styles.jsonentry N. IfwebkitTextFillColor === 'rgba(0, 0, 0, 0)'ANDbackgroundImagecontainsradial-gradientorlinear-gradient— yes, painted. Extract the gradient stops verbatim into design.md. - Note tracking sign:
letterSpacingnumeric — positive or negative? Display-font tracking is editorial signal.
3d — Cards (run for card-0.png, card-1.png, card-2.png)
For each card screenshot:
Read card-N.png.- Describe: solid surface, gradient surface, border-only, glassmorphism? Hover affordance?
Read cards-inventory.jsonfor exact bg/border/radius/shadow values.- If multiple cards share the same recipe — write ONE card recipe in design.md, not three.
3e — Color extraction discipline
By the time you've read 8-12 PNGs, you've seen the palette. Compile the canonical token list:
- 2-3 canvas/surface levels (background, raised surface, nested surface)
- 3 text levels (primary, secondary, muted)
- 1 brand accent (the color of the primary CTA you identified)
- 0-3 secondary accents (only if you saw clearly distinct accent uses)
- 4 status colors — if the site doesn't use status states obviously, use generic green/blue/amber/red-300 from Tailwind (this is fine, status is generic)
Do not invent accents you didn't see. Do not copy every color the site happens to use into a token (e.g. a s