pi-heartbeat
Configure periodic health checks via HEARTBEAT.md and the /heartbeat command.
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
$ npx -y skills add espennilsen/pi --skill extract-design-system --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/extract-design-systemContext preview
The summary Claude sees to decide when to auto-load this skill.
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
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
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
Run the extraction script against the target URL:
node scripts/extract.mjs <url> [outDir] [subpage1,subpage2,...]
Examples:
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.
{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 datanode scripts/extract.mjs "TARGET_URL" "extracted-design-system" "/about,/pricing"
The script automatically:
The script captures computed values. This step catches declared values from CSS source that may not be active on the current page:
# 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
Review `raw/colors.json`, `raw/typography.json`, `raw/spacing.json` and the screenshots. Then organize into a structured token file.
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.
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+ |
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.
For each component in the screenshots, document:
This repository is my Pi coding agent home directory. I keep it under version control and symlink it to ~/.pi/agent so Pi loads configuration, extensions, skills, and runtime state from here.
Configure periodic health checks via HEARTBEAT.md and the /heartbeat command.
Manage persistent memory across sessions. Use when asked to remember, recall, forget, or review what was stored. Covers long-term…
Track and manage projects with git status via dashboard and tool.
Delegate tasks to specialized subagents for parallel or sequential execution.
Audit, generate, update, and lint AGENTS.md files across all projects. Use when asked to check project context files, scaffold…