extract-design

Extract a complete design system — colors, typography, spacing, components, shadows, and W3C design tokens — from any live website using Dembrandt. Runs a headless browser against the URL and returns real computed values from the DOM. Use when you need a site's actual design tokens, want to reverse-

By dembrandt · 615 installs

npx skills add dembrandt/dembrandt-skills --skill extract-design

Source repository · Upstream listing

Extract Design — Dembrandt Dembrandt runs a headless Chromium browser against any URL, walks up to thousands of DOM elements, reads computed CSS, and returns a structured design system: colors with confidence scoring, typography styles, spacing scale, border radius, borders, shadows, and interactive component styles. How to Run MCP Usage (async by default) To expose Dembrandt as MCP tools, add this server to the agent's MCP config (no install — npx fetches it on first run): When using the Dembrandt MCP server, all extraction tools return a job id immediately rather than blocking. Poll get job status until status is "completed" : Hand the job id to the analysis tools instead of passing the extraction back. Every pure tool accepts it, and the queue keeps the whole extraction for an hour, so a job started by a narrow tool such as get color palette still feeds export dtcg . Passing the extraction inline works and wins when you give both, but a real extraction is far too large to travel back through the model as a tool argument. [dembrandt 0.29+] Pass sync: true to any extraction tool to block and return the result directly (useful on fast networks, risks timeout on slow sites, and proportionally slower when pages is above 1). Extraction tools: get design tokens (everything), get color palette , get typography , get component styles , get surfaces , get spacing , get brand identity , get motion (durations, easings, named keyframes, hover patterns, and the gradients that travel with them) [dembrandt 0.36+]. All accept slow , mobile (mobile viewport), and cookie (cookie string for authenticated pages); get design tokens and get color palette also accept darkMode and wcag (contrast analysis). [dembrandt 0.23.1+ for mobile/cookie/wcag] Every extraction tool also crawls, which is the single biggest lever on token quality: one page gives you one page's tokens. [dembrandt 0.29+] Option What pages Extract up to N pages and merge them into one token set (1 to 20). Pages come from DOM links, or from sitemap.xml when sitemap is true paths Name the extra paths explicitly, e.g. ["/pricing", "/docs"] . Overrides discovery sitemap Discover from sitemap.xml. Alone it takes up to 20 pages; pages caps it header Extra HTTP headers, a string or a list, e.g. "Authorization: Bearer ..." , for pages a cookie cannot reach cookieFile Path to a saved session: a JSON cookie array, a Playwright storageState file (cookies, localStorage, and the sessionStorage block save storage state adds), or Netscape cookies.txt. The operator produces it once with dembrandt <url login save storage state <path ; an agent cannot sign in itself [dembrandt 0.39+] basicAuth HTTP Basic credentials as "user:password" for staging hosts behind a browser prompt [dembrandt 0.39+] userAgent Custom user agent string noSandbox Disable the browser sandbox. Required inside Docker and most CI containers, where launch otherwise fails A page that fails to load is dropped and the merge carries the rest, so a crawl does not fail on one bad URL. Pure tools (no browser, synchronous; the extraction goes in result , or name a completed job with job id [dembrandt 0.29+]): compute drift (0 100 drift score between two extractions; takes baselineJobId and candidateJobId as the job based form), get findings (design system lint: contrast, consistency, duplication), export dtcg (W3C Design Tokens format), generate design md (DESIGN.md brand guide), render report (self contained HTML report), export tailwind (Tailwind v4 @theme block), export shadcn (shadcn/ui theme, slots left at shadcn's defaults where the page supplied nothing). Job control: get job status , list jobs , cancel job . [dembrandt 0.23.1+ for get findings/export dtcg/generate design md/list jobs, 0.36+ for the two emitters] Three tools take their own input rather than an extraction [dembrandt 0.36+]: validate dtcg (check a DTCG document against the 2025.10 spec, including one this server produced, so a hand edit cannot quietly break it), check contrast (grade colour pairs you name against WCAG 2.1 at the threshold the text size earns, for colours you are about to ship rather than ones already on a page), and check robots (ask whether robots.txt allows a URL before spending a browser run on it). Note: npx runs a dembrandt already on PATH in preference to fetching the latest, so a globally installed dembrandt silently shadows it. Symptom: options the pinned version supports are rejected as unknown, or a crawl returns a single page. Check with dembrandt version and upgrade the global install, or point the MCP config at an explicit path. Note: dembrandt <=0.23.0 fails to start via the npx one liner above ( McpDepsMissingError ) — the MCP SDK was an optional peer dependency. Fixed in 0.23.1; require it. Output Structure Dembrandt returns a structured object. The key sections: Working with Extracted Tokens Seeding a Tailwind theme (dembrandt 0.28+) Don't hand map the JSON. tailwind writes a Tailwind v4 @theme block directly: Observed values only: no 50–950 shade ramps, no interpolated scale steps, no derived hover or on colour variants. An invented shade is indistinguishable from a measured one once it is in the file, so the export is a starting point you extend by hand. Colours keep their semantic role name ( color primary ) or the page's own custom property name where one is declared; the rest are numbered color brand N . Spacing collapses to v4's spacing multiplier when the page has a base N rhythm, and falls back to named steps otherwise. Tailwind's defaults still apply to anything not listed, so the block extends the theme rather than replacing it. v4 only. For a v3 tailwind.config.js , map the output by hand — colors.semantic → theme.colors , typography.styles → fontFamily , spacing.commonValues → spacing , borderRadius.values → borderRadius , shadows → boxShadow . Seeding a shadcn/ui theme shadcn (0.34.0+) writes the theme, so do not hand map the variables: The file carries the :root block and the @theme inline mapping Tailwind v4 needs, in oklch. A slot is written only where the page supplied a value; the rest are named in the file header and left to shadcn's own defaults, so an unobserved slot never arrives as a plausible value that reads as measured. dark mode produces the .dark block, one colour scheme per run. Do not derive radius from borderRadius.values[0] : that list is sorted by length, so the first entry is the smallest radius on the page, not the one its buttons and inputs use. The flag takes the most used value. Reading confidence levels Dembrandt scores every color by semantic context: Confidence Meaning high Appears on semantically labeled elements (buttons, CTAs, headers with brand classes). Almost certainly a brand color. medium Moderate frequency or moderate context. Likely a brand color. low Rare, low semantic context. May be a one off or component specific color. Since 0.28.0 confidence also has a usage floor, as spacing and radii always had: a colour seen once caps at low, twice at medium, and high needs three occurrences whatever its semantic context scores. Hover and focus colours are the exception and keep medium — their single occurrence is provenance, not a usage claim. Start with high confidence colors when building a palette. Include medium for full coverage. Treat low as reference only. Colour notation Never convert a colour by hand and never re derive one with your own maths. Every palette entry and every CSS variable already carries lch and oklch alongside the hex, so read the field you need straight from the JSON. color format only changes what the terminal prints, so it is the wrong tool when you are consuming JSON or MCP output. Use hex ( normalized ) as the identity of a colour: it is what dedup, drift comparison and every downstream tool key on. Two entries with the same hex are the same token even when their emitted notations differ. When an author declared a token in a modern notation, cssVariables[name].value preserves it exactly, which is what you want when writing CSS back into that codebase, since it keeps the author's own notation and stays inside their gamut. Flags Reference Flag What it does json only Clean JSON to stdout — pipe into files or tools save output Save JSON to output/<domain /<timestamp .json dtcg W3C Design Tokens Community Group format. A shadow token's $value is an array when the shadow has more than one layer, so a consumer reading $value.offsetX must branch on Array.isArray . (0.32+) design md Generate DESIGN.md — prose first brand doc html [path] Self contained HTML report (inline CSS, embedded JSON). Open offline or attach as a CI artifact. (0.19+) compare <baseline.json Diff against a saved extraction; prints a drift verdict and exits 1 on drift. CI gate. (0.19+) brand guide Generate a PDF brand guide dark mode Extract dark color scheme and merge into palette mobile Extract at 390px mobile viewport crawl <n Crawl up to N pages and merge tokens sitemap Discover pages from sitemap.xml slow 3× timeouts — use on slow loading or JS heavy sites screenshot <path Save a full page screenshot raw colors Include pre filter raw colors in JSON output color format <fmt Notation for colors printed to the terminal: hex (default), rgb , oklch , lch , source (as authored). Presentational only, so JSON output is unchanged, and export paths ignore it. (0.28+) tailwind [path] Write a Tailwind v4 @theme CSS file — observed values only. Defaults to output/<domain /theme.css . (0.28+) shadcn [path] Write a shadcn/ui theme — observed slots only, @theme inline included. Defaults to output/<domain /shadcn.css . (0.34+) browser firefox Use Firefox instead of Chromium stealth Opt in anti detection: navigator spoofing + human mouse simulation. Use only when authorized. user agent <string Custom user agent string locale <string Browser locale, e.g. fi FI , en GB (default: en US ) timezone <string Browser timezone, e.g. Europe/Helsinki (default: America/New York ) accept language <string Custom Accept Language header value header <string Extra request header as Name: value ; repeat the flag for several (repeatable from 0.39) screen size <WxH Physical screen resolution to report, e.g. 1920x1080 Drift Detection & CI (dembrandt 0.19+) compare turns extraction into a gate. Save a known good baseline, then compare later extractions against it: Runs the canonical drift engine over structured tokens — deterministic, not a pixel/render diff. Exit code: 0 stable, 1 drift. Gates a pipeline directly. html writes a self contained report; with compare it includes a drift banner (added/removed/changed tokens). Attach it as a CI artifact. Baselines churn once on 0.28.0. Three fixes move colour and typography values: the palette usage floor, body ending at the 24px reading range (non heading text above it takes text , so hero copy stops landing on the body token), and families under 2% of counted text being dropped. Measured on dembrandt.com against a 0.27.1 extraction, drift came out at 15 against a threshold of 10 — enough to fail a gate. On the first run after upgrading, re approve with compare <baseline approve or regenerate the baseline. Drift after that is real drift. 0.32.0 needs no re approval. Schema 1.12.0 measured 7 and 6 against a threshold of 10 on two reference sites, the only difference being the added mono context. The