Reverse-engineer a design system from a live website (public URL or localhost). Extracts colors, typography, spacing, shadows, radii, breakpoints, and component patterns using a headed Playwright browser. Captures screenshots of pages, components, and interactive states at real device resolutions. Produces structured design tokens and optionally seeds a Penpot project. **Triggers — use this skill when:** - User says "extract design system from [url]" - User asks to "reverse-engineer the styl...
Scanned 9/12/2026
Install to Claude Code
npx -y skills add espennilsen/pi --skill extract-design-system --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Extract Design System?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/espennilsen-extract-design-system)More formats (shields.io, HTML) on the badges page.
---
name: extract-design-system
description: >
Reverse-engineer a design system from a live website (public URL or localhost).
Extracts colors, typography, spacing, shadows, radii, breakpoints, and component
patterns using a headed Playwright browser. Captures screenshots of pages,
components, and interactive states at real device resolutions.
Produces structured design tokens and optionally seeds a Penpot project.
**Triggers — use this skill when:**
- User says "extract design system from [url]"
- User asks to "reverse-engineer the styles from [site]"
- User says "build a design system based on [website]"
- User asks to "pull the design tokens from [url]"
- User says "analyze the design of [site]"
- User asks to "import styles from [website] into Penpot"
- User points at a URL and asks about its colors, fonts, spacing, or components
---
# Extract Design System from Website
Reverse-engineer a complete design system from a live website using two passes:
1. **CSS source analysis** — fetch and parse stylesheets for declared values
2. **Headed Playwright extraction** — visually browse the site, interact with elements,
extract computed styles, and capture screenshots at real device resolutions
## Prerequisites
- Playwright installed (`npx playwright install chromium` if not set up)
- `web_fetch` tool for fetching raw HTML/CSS source
## Quick Start
Run the extraction script against the target URL:
```bash
node scripts/extract.mjs <url> [outDir] [subpage1,subpage2,...]
```
Examples:
```bash
node scripts/extract.mjs https://example.com
node scripts/extract.mjs https://example.com ./my-tokens "/about,/pricing,/docs"
node scripts/extract.mjs http://localhost:3000 extracted "/dashboard,/settings"
```
The script opens a **visible browser** (`headless: false`) so you can watch the
extraction. It uses real device profiles for accurate screenshots:
| Breakpoint | Device | Viewport | DPR | Real image size |
|------------|--------|----------|-----|-----------------|
| Mobile | iPhone 15 | 393×659 | 3x | 1179×1977 |
| Tablet | iPad Pro 11 | 834×1194 | 2x | 1668×2388 |
| Desktop | — | 1440×900 | 2x | 2880×1800 |
| Wide | — | 1920×1080 | 2x | 3840×2160 |
Mobile and tablet use Playwright's built-in device descriptors (correct UA,
`isMobile`, `hasTouch`) so sites serving different layouts render correctly.
## Output Structure
```
{outDir}/
├── screenshots/
│ ├── pages/ — full-page at 4 breakpoints × each page
│ │ ├── home-mobile.png
│ │ ├── home-desktop.png
│ │ ├── home-dark-mode.png
│ │ └── ...
│ └── components/ — isolated component + hover/focus states
│ ├── nav.png
│ ├── button-primary.png
│ ├── button-primary-hover.png
│ ├── button-primary-focus.png
│ ├── nav-mobile-open.png
│ └── ...
└── raw/
├── colors.json — CSS custom properties + computed colors
├── colors-dark.json — dark mode variables (if detected)
├── typography.json — font families, type styles, @font-face
├── spacing.json — spacing, radii, shadows, borders, max-widths
└── components.json — component manifest + responsive layout data
```
## Workflow
### Step 1: Run the Extraction Script
```bash
node scripts/extract.mjs "TARGET_URL" "extracted-design-system" "/about,/pricing"
```
The script automatically:
- Extracts CSS custom properties and computed colors from 800 sampled elements
- Captures typography from all semantic elements (h1-h6, p, a, button, etc.)
- Measures spacing, radii, shadows, and borders
- Screenshots every page at 4 breakpoints with real device contexts
- Isolates and screenshots 17 common component types
- Captures hover and focus states on interactive elements
- Tests mobile nav by clicking hamburger-like buttons at iPhone viewport
- Detects dark mode via `prefers-color-scheme` emulation and toggle sniffing
### Step 2: CSS Source Analysis (supplementary)
The script captures computed values. This step catches declared values from CSS
source that may not be active on the current page:
```bash
# Fetch stylesheets identified in the HTML
web_fetch <stylesheet-url>
# Look for things the computed pass might miss:
# - Media query breakpoints
# - Keyframe animations
# - CSS custom property definitions with fallbacks
# - Commented-out or unused styles that reveal design intent
```
### Step 3: Organize Raw Data into Tokens
Review `raw/colors.json`, `raw/typography.json`, `raw/spacing.json` and the
screenshots. Then organize into a structured token file.
#### Colors → Palette
Group extracted colors into categories:
| Category | What to look for |
|----------|-----------------|
| **Primary** | Brand color, CTA buttons, most prominent accent |
| **Secondary** | Supporting accent, secondary buttons |
| **Neutral** | Backgrounds, text, borders — the gray scale |
| **Success** | Green tones (confirmations, checkmarks) |
| **Warning** | Yellow/amber tones (alerts) |
| **Error** | Red tones (errors, delete actions) |
| **Info** | Blue tones (informational messages) |
Deduplicate near-identical colors (ΔE < 3 in OKLCH space). A site with 47
slightly different grays probably intended 5-8.
#### Typography → Scale
Map extracted font sizes to a named scale:
| Name | Size range |
|------|-----------|
| caption | ≤12px |
| small | 13-14px |
| body (base) | 15-16px |
| large | 17-18px |
| h6-h1 | 18-48px |
| display | 48px+ |
#### Spacing → Grid
Snap raw pixel values to the nearest standard grid:
```
4px grid: 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80, 96
8px grid: 8, 16, 24, 32, 40, 48, 56, 64, 80, 96
```
Pick whichever grid the extracted values align to with the least rounding.
#### Components → Inventory
For each component in the screenshots, document:
- Visual appearance (size, colors, spacing)
- Variants observed (different sizes, states)
- Interactive behavior (from hover/focus screenshots)
- Closest shadcn-svelte equivalent
### Step 4: Compile Token File
Write the organized data to `tokens.json`:
```json
{
"$schema": "extracted-design-tokens",
"source": "https://example.com",
"extracted": "2026-03-09",
"framework_detected": "tailwind|bootstrap|custom|none",
"dark_mode": true,
"colors": {
"light": {
"primary": { "50": "#...", "500": "#...", "900": "#..." },
"neutral": { "50": "#...", "950": "#..." }
},
"dark": { }
},
"typography": {
"fontFamilies": { "sans": "...", "mono": "..." },
"scale": { "h1": { "size": "36px", "weight": 700, "lineHeight": 1.2 } }
},
"spacing": { "grid": "4px", "scale": [0, 4, 8, 12, 16, 24, 32, 48, 64, 96] },
"radii": { "sm": "4px", "md": "8px", "lg": "12px" },
"shadows": { "sm": "...", "md": "...", "lg": "..." },
"components": { "buttons": { "variants": ["primary", "secondary"] } }
}
```
### Step 5: Seed Penpot (optional)
If requested, create a Penpot project from the tokens using `pi-penpot`:
1. Create project named after the source site
2. Create a "Design System" page with color swatches, type samples, spacing ruler
3. Create pages for each major screen, importing screenshots as references
4. Build components matching the extracted inventory
### Step 6: Generate Tailwind Config (optional)
Map tokens to a Tailwind config with CSS custom properties for runtime theming.
## Tips
- **Pass 3-5 subpages** for broader component coverage
- **CSS custom properties are gold** — sites using them have self-documented tokens
- **Watch the browser** — headed mode reveals cookie banners, auth walls, and popups that block extraction
- **Interactive states matter** — hover/focus screenshots catch design intent static captures miss
- **Don't over-extract** — focus on intentional design decisions, not every computed value
- **Remove `slowMo`** in the script for faster extraction once verified
- **Check for dark mode** — the script detects it automatically via both `prefers-color-scheme` and toggle buttons
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!