From data-liberation
Completes a semantic design foundation (color, typography, spacing) from aggregate CSS analysis and representative HTML. Use after liberation and before theme generation.
How this skill is triggered — by the user, by Claude, or both
Slash command
/data-liberation:design-foundationsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You build a coherent **design foundation** — a semantic, reviewable intermediate between raw SP1 token observations and WordPress theme generation.
You build a coherent design foundation — a semantic, reviewable intermediate between raw SP1 token observations and WordPress theme generation.
The agent gives you:
PartialDesignFoundation JSON blob (the output of liberate_design_foundation_scaffold). Some roles are already filled in by deterministic rules. The remaining slots are null, listed in skillTodos.palette.json, typography.json, breakpoints.json, and when present computed-styles.json.<outputDir>/html/homepage.html).liberate_design_foundation_validate.Vision context is the dominant cost in this skill. The normal path should not open screenshots. Use rendered HTML, aggregate computed CSS, and deterministic scaffold evidence first.
If the invoking runner provides a Foundation sample JSON, that sample is a hard cap: do not inspect HTML outside the listed entries. Use aggregate palette.json, typography.json, breakpoints.json, and computed-styles.json for broad frequency and component signals. Use only the sampled HTML for semantic role decisions.
Step 1 — aggregate CSS analysis (cheap):
Read aggregate analysis before opening any visual asset:
palette.json: high-frequency background colors.typography.json: observed font families, sizes, weights, and line heights.computed-styles.json: component-level text, background, border, radius, padding, typography, and background-image evidence for selectors like header, footer, a, button, form controls, hero/card/CTA containers.breakpoints.json: responsive tier evidence.These files are generated from the live DOM using browser-computed CSS. They are the source of truth for colors and typography; screenshots are not needed to discover tokens.
Step 2 — inspect the representative HTML (cap):
Use the provided Foundation sample. In the fast path it contains at most one representative rendered HTML file, preferring the homepage. Inspect it for:
<header>, <footer>, <main> boundaries.Step 3 — screenshot fallback only when needed:
Open a screenshot only if HTML/CSS evidence cannot answer a specific semantic question, for example:
hero background, cta banner, decorative) and HTML class names are unclear.If you open a screenshot, state exactly what ambiguity it resolved. Do not read all screenshots.
Return a complete DesignFoundation matching the schema documented in src/lib/design-foundation/schema.ts. The JSON must pass liberate_design_foundation_validate with { ok: true }.
You MUST call liberate_design_foundation_validate on your output before returning. If it returns errors, fix them and re-validate. Do not return until validation passes.
The scaffold fills:
color.surface.base — lightest high-frequency palette entrycolor.text.default — darkest high-frequency palette entrytypography.families.body — most-common body fontFamilybreakpoints.{sm,md,lg,xl} — nearest-tier mappinggradient.* — CSS strings (roles marked "TODO")inputsDigest.* — sha256sYou fill everything else. Use the criteria below.
| Role | How to pick |
|---|---|
raised | A slightly-darker-or-lighter palette entry commonly used for cards, alternate sections, subtle containers. Prefer computed-styles.json selectors like card/section containers and representative HTML class names. |
inverse | A saturated dark entry commonly used as a dark hero / footer background. Usually appears on most pages in header/footer patterns. |
| Role | How to pick |
|---|---|
muted | A mid-lightness entry used for secondary labels, placeholders, metadata. Usually appears in button labels, form hints, deemphasized text. |
inverse | Near-white; used on inverse surfaces (dark hero text, footer text). |
subtle | A very-light-on-light or very-dark-on-dark entry used for placeholder/ghost text. Often #999, #ccc, or the equivalent inversed on dark. |
Distinguish by saturation, frequency, and usage signal:
| Role | How to pick |
|---|---|
primary | The dominant saturated color used on primary CTAs (Book a Demo, Sign Up, etc.). Usually visible on the homepage hero and most page footers. |
primaryAlt | A slightly-varied primary (darker for hover state, or a closely-related hue used in gradients with primary). |
warning | A red / warm orange used for urgent CTAs, alerts, "important" banners. Often appears on pricing or trial pages. |
warm | A secondary accent in the orange/coral family used as a visual counterweight to primary. |
highlight | A yellow / gold used in gradients or for highlighted text. Usually low-frequency but visually prominent where it appears. |
Ambiguity rule: If two entries both look like primary candidates, pick the one with higher urls (more pages). If still tied, pick the one with higher saturation.
| Role | How to pick |
|---|---|
default | A light-grey entry commonly used as a hairline divider (often #ccc, #ddd). |
subtle | A lighter grey (or a tinted alternative) used inside low-contrast containers. |
The scaffold fills body. Fill:
| Role | How to pick |
|---|---|
display | The family used for the largest headlines (h1, hero titles). Often a serif or display face. Check typography.h1 entries in the raw SP1 file. |
mono | A monospace family used for tags, labels, small caps. Check typography entries with fontFamily containing "Mono", "Courier", or "Code". If no mono family is observed, set to null — do NOT hallucinate one. |
Scaffold fills css and evidence; you fill role. Map each gradient to its usage:
hero background — dark, full-bleed, used as page hero/header backgroundcta banner — used on call-to-action bands and subscribe blocksheadline accent — light-to-highlight gradients used with background-clip: text on headlinesdecorative — anything elseLook at the HTML excerpt to see which selectors use the gradient.
Fill all five with token references (not raw values). Reference form: "color.accent.primary", "radius.base", "spacing.4".
| Component | Required tokens |
|---|---|
button | background (accent.primary), text (text.inverse), radius (radius.base), padding, fontFamily (families.body), fontWeight |
input | background (surface.base), border (border.default), text (text.default), radius, padding |
card | background (surface.base or surface.raised), border (border.subtle), radius (radius.lg), padding |
surface | background (surface.base) — baseline container |
divider | background (border.default), height (e.g. "1px") |
Flag things that will affect downstream theme generation:
Fraunces, Playfair).references/theme-tokens.md ("Commercial / uncapturable → free substitution"). Record the substitution as an openQuestion (blocksReplica:false) noting which family was swapped (e.g. quasimoda → Hanken Grotesk) so an operator can confirm the visual match; do NOT leave the family as a bare sans-serif fallback.Each entry: { id: "short-slug", question: "Confirm ...", blocksReplica: true|false }.
Every role you fill must have at least one evidence entry. Good evidence:
"palette[5]: 92/186 urls, 341 occurrences" (cites raw SP1 frequency)"computed button background on homepage.html" (cites HTML + element)"hero section @ screenshots/desktop/homepage.png" (cites screenshot)Bad evidence:
"looks like primary" (no citation)"skill-filled" (placeholder — unacceptable)skillTodos.skillTodos:
null AND remove its path from skillTodos. This communicates "deliberately empty" instead of "forgot to fill."components with the fixed set above.openQuestions with any concerns.skillTodos: [] once every remaining slot is filled.liberate_design_foundation_validate. If it fails, fix and retry.serif family but the agent seems to want one, do NOT invent "Merriweather". Leave display: null and add an openQuestion about font substitution.liberate_design_foundation_validate before returning.primary, flag the tie in openQuestions rather than silently picking one.The deterministic scaffold can be misled by markup that isn't the real page design. These are common enough to check explicitly — when you see them, the slot IS "demonstrably wrong," so correct it against palette.json frequency + a screenshot and note the correction in openQuestions:
color.surface.base and color.text.default from a low-frequency :root/component CSS var (e.g. --tooltip-background-color) instead of palette frequency — producing surface.base: "black" / text.default: "white" on a site that's actually white-background/dark-text. Sanity check: if surface.base is dark or text.default is light, verify against palette.json — the dominant high-count entry is the real surface; the darkest high-count entry is the real text. Swiftlumber (2026-05-28): scaffold gave black/white from a 1-url tooltip var; palette showed #ffffff×57 / #000000×3 → corrected to #fff/#000.<body>. typography.scale.base (and typography.body.fontSize) can read ~10px from a visually-hidden SEO body element. Real body copy is ~16px (check typography.scale.steps.base). Reconstruction uses captured per-element sizes, so this rarely changes output — but flag it in openQuestions so it isn't trusted downstream.h1/h2 may report a hidden-SEO face (e.g. orig_sf_pro_display_bold, wfont_*) that is NOT the visible heading face. Cross-check h3/visible headings — the real display family often surfaces there (swiftlumber: visible headings are "libre baskerville", serif from h3; h1/h2 were the SEO SF-Pro face).Input partial (relevant slots only):
{
"color": {
"accent": { "primary": null, "warning": null, "highlight": null }
},
"skillTodos": ["color.accent.primary", "color.accent.warning", "color.accent.highlight"]
}
Screenshot evidence: homepage CTA button is teal; "Book a Demo" button is red; headline text has a gold→red gradient.
Output:
{
"color": {
"accent": {
"primary": {
"value": "#00a4bd",
"role": "primary CTA, link",
"evidence": [
"palette[5]: 40/100 urls, 200 occurrences",
"[email protected] computed background"
]
},
"warning": {
"value": "#f2545b",
"role": "urgent CTA (Book a Demo)",
"evidence": [
"palette[7]: 30/100 urls",
"[email protected] computed background"
]
},
"highlight": {
"value": "#ffc700",
"role": "gradient highlight",
"evidence": [
"gradient.headlineAccent uses #ffc700 → #cc0201",
"h1 [email protected]"
]
}
}
},
"skillTodos": []
}
Then call liberate_design_foundation_validate and return.
npx claudepluginhub automattic/data-liberation-agent --plugin data-liberationExtracts design system from websites, HTML files, or screenshots into DESIGN.md via Playwright automation, HTML inspection, and visual analysis for UI consistency.
Extracts the complete design language (colors, typography, spacing, shadows) from any website URL. Generates 8 output files: Tailwind config, React theme, shadcn/ui theme, Figma variables, W3C design tokens, CSS variables, AI-optimized markdown, and visual HTML preview. Also runs WCAG accessibility scoring.
Extracts a complete design system from a WordPress site (colors, typography, spacing, components) and persists it as reusable tokens. Also generates a visible style-guide page on the site.