CLI tool
dembrandt/dembrandt avatar
dembrandt/dembrandt

Dembrandt: extract a website's design tokens from the command line

Extract any website’s design system into tokens in seconds: logo, colors, typography, borders & more. One command.

3,599 stars318 forksTypeScriptMIT

At a glance

What is it?
Dembrandt renders a page in Chromium, reads computed styles, and returns colors, typography, spacing, borders, shadows and motion as tokens. It is a single npm install, and the browser step is the first thing that trips people up.
Who is it for?
Adopt Dembrandt if you need a token set from a page you do not control, or a CI gate that fails when a preview deployment drifts from a committed baseline. Skip it for canvas or WebGL interfaces, since the README states there is no DOM to read, and for anything where you need hover and focus states captured from real interaction rather than from CSS.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 4, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Dembrandt extracts, and who needs that

The package describes itself as extracting design tokens and publicly visible CSS information from any website. The output list in the README is long: colors split into semantic, palette, CSS variables and gradients; typography with fonts, sizes, weights, sources and font file URLs; spacing scales from margin and padding; borders with radius, widths, styles and colors; shadows; motion with a duration scale, easing curves and hover patterns per component type; components covering buttons, badges, inputs and links; breakpoints; and detected icons and frameworks.

The audience is narrower than that list suggests. This is for design engineers and frontend developers who need a token set for a site they did not build, or who want a machine-checkable record of what a site's design system currently looks like. Competitive benchmarking is one use. Auditing a legacy stylesheet before a rewrite is another. The README also points at a recipes page, filtered by role, covering competitor benchmarking, WCAG audits, Figma token push and agentic design system builds.

It is not a design tool. Nothing here lets you author tokens, preview them on a page, or push them into a running application. It reads a rendered page and writes files or terminal output. If you already have a maintained token source, Dembrandt is useful mainly as the thing that tells you when the live site has stopped matching it.

How the extraction actually works

The README is explicit about the mechanism: Playwright renders the page, dembrandt reads computed styles from the DOM, analyzes color usage and confidence, groups similar typography, detects spacing patterns, and returns design tokens. That ordering matters. Nothing is parsed from raw CSS text alone. The values come from the browser's computed styles, which means cascade, inheritance and media queries have already been resolved by the time dembrandt looks at them.

The confidence and grouping steps are the interesting part. A page rarely uses one spacing value per role, and it rarely uses a color exactly once. The tool has to decide which of the observed values are the system and which are one-offs, and the README's phrase for this is analyzing color usage and confidence. The Tailwind export is described as observed values only, which is a useful boundary to keep in mind: the output reflects what the page did, not what its source intended.

Crawling changes the quality of the result. The README states that setting pages above 1 to crawl and merge several pages produces a markedly stronger token set than one page, with cross-page confidence boosting. The CLI exposes this as --crawl 10, and the MCP tool accepts pages, paths and sitemap, where paths names pages explicitly and sitemap discovers them from sitemap.xml. If you extract a single page and the token set looks thin, that is the reason given in the documentation.

Installing Dembrandt and running a first extraction

Dembrandt requires Node.js 18 or higher. The README's install section is three lines, and the middle one is not optional. The tool drives Chromium through playwright-core, which ships no browser binaries, so a fresh install has nothing to launch.

bash
npm install -g dembrandt
dembrandt install-browser        # one-time: fetches the matching Chromium
dembrandt dembrandt.com

The README states that skipping the browser step fails with browser engine not available. Browsers land in a shared Playwright cache, so this only needs doing once per machine, and the same step applies if you go the npx route instead of a global install.

By default you get formatted terminal output and nothing else. To keep a copy, pass --save-output, which writes JSON to output/dembrandt.com/TIMESTAMP.json. The other export flags change the shape of the result rather than the extraction itself:

bash
dembrandt dembrandt.com --save-output   # Save JSON to output/dembrandt.com/TIMESTAMP.json
dembrandt dembrandt.com --dtcg          # W3C Design Tokens (DTCG) export
dembrandt dembrandt.com --design-md     # DESIGN.md for AI agents
dembrandt dembrandt.com --tailwind      # Tailwind v4 @theme CSS, observed values only
dembrandt dembrandt.com --wcag          # WCAG 2.1 contrast, real DOM pairs with AA/AAA grades
dembrandt dembrandt.com --crawl 10      # Merge 10 pages into one output
dembrandt dembrandt.com --slow          # 3x timeouts for JavaScript-heavy sites

The --dtcg flag is the one to reach for if you feed Style Dictionary or Tokens Studio, since it emits W3C Design Tokens. The --design-md flag answers a different need: a markdown description of the design system for an AI agent to read. The README points to docs/usage.md for the full flag reference, including mobile and dark mode, browser selection and CDP, brand guide PDF, motion tokens and fingerprint options. If a site times out, --slow triples the timeouts, which is the documented response to JavaScript-heavy pages.

Gating a pull request on token drift

The CI story is the part of the project with the clearest contract. Extract a preview deployment, compare it against a committed baseline, and fail the job when tokens moved. The README gives the GitHub Action form directly:

yaml
- uses: dembrandt/[email protected]
  with:
    url: https://preview.example.com
    baseline: .dembrandt/baseline.json

The action annotates the pull request with the drifted tokens. On any other runner the gate reduces to an exit code plus JSON: dembrandt URL --compare baseline.json --json-only exits 1 on drift and prints per-token changes[]. That is a clean separation. The GitHub Action gives you annotations; the underlying command gives you a boolean and a machine-readable diff, which is what you want in GitLab CI, Buildkite or a shell script. The README points to docs/ci.md for the Action inputs, the platform-neutral gate and the exit code table.

The practical constraint is the baseline file. It has to be committed and it has to be regenerated deliberately, not on every run, or the gate compares the site against itself and never fires. The repository ships examples/drift-gate.yml alongside examples/carbon.design.json and examples/material.io.json, which is a reasonable place to look before writing your own workflow.

Wiring Dembrandt into an AI agent over MCP

Dembrandt ships a second binary, dembrandt-mcp, and the package.json declares mcpName as io.github.dembrandt/dembrandt. It works as a tool in Claude Code, Cursor, Windsurf, or any MCP-compatible client. The README's example is a single command:

bash
claude mcp add --transport stdio dembrandt -- npx -y --package dembrandt dembrandt-mcp

Alternatively you add it to a project's .mcp.json, which is the better choice if the configuration should be shared with a team rather than living in one person's client settings.

The tool surface splits into two halves, and the split is worth understanding before you write prompts. Extraction tools such as get_design_tokens, get_color_palette, get_typography, get_component_styles, get_surfaces, get_spacing and get_brand_identity do the browser work. Pure analysis tools such as compute_drift, get_findings, export_dtcg, generate_design_md and render_report do not.

The README describes the pattern: extraction returns a job_id, you poll it with get_job_status, then hand that same id to the pure tools instead of passing the extraction back as an argument. That is a deliberate design choice, and it matters because token sets are large. Passing a full extraction through a model's context on every call would be wasteful and slow. Job ids keep the data on the server side of the MCP boundary. Extraction tools accept slow, mobile, darkMode, wcag, cookie and header for authenticated pages, userAgent, and noSandbox for Docker and most CI containers. The README also points at a companion repository, dembrandt-skills, installed with npx skills add dembrandt/dembrandt-skills, which adds UX analysis on top of the extracted tokens.

Where Dembrandt does not work

The README's limitations section is short and honest, and two entries in it are disqualifying for whole categories of sites. Canvas and WebGL-rendered sites cannot be analyzed, because there is no DOM to read. If the interface you care about is drawn into a canvas element, Dembrandt will return nothing useful, and no flag changes that. This is the clearest case where it is the wrong tool.

The second is hover and focus states, which the README says are extracted from CSS rather than from full interaction. So a component whose pressed state is applied by JavaScript at click time may not appear in the motion or component output. Treat the hover patterns as a reading of what the stylesheets declare, not a recording of what the page does.

Dark mode is a third constraint, and it is a flag rather than a detection. The README states that dark mode requires --dark-mode and is not automatically detected. If you need both themes, you are running two extractions and reconciling them yourself. The README's limitations section is truncated in the text available here, so there may be further caveats beyond these.

There is also a structural limitation that follows from the approach rather than from the README. Because values come from computed styles on a rendered page, anything that only exists behind authentication, geolocation or an A/B test will not appear unless you supply it. The MCP tools accept cookie and header for authenticated pages, which is the documented workaround, but the CLI flag list in the README does not mention an equivalent, so check docs/usage.md before assuming the CLI can reach a logged-in page.

How it compares with hand-reading DevTools or a Figma plugin

The obvious alternative is opening the site in a browser and reading the computed styles panel yourself. That is free, needs no install, and works on canvas and WebGL sites because you are looking at the rendered result rather than waiting for a DOM read. It also scales badly. Reading one page's colors is quick; building a spacing scale, a duration scale and a set of easing curves across ten pages by hand is not, and doing it again next month to see what changed is worse.

The other common alternative is a Figma plugin that pulls styles from a design file. That operates on the source of truth rather than the deployed result, which is better when the design file is authoritative and worse when it is not. Dembrandt's whole premise is the opposite direction: it reads what shipped. The README's own topics list includes token-drift and reverse-engineering, and that framing is accurate. If your design file and your production site have diverged, a Figma plugin will not tell you, and Dembrandt will.

A third approach is writing your own Playwright script. The pieces are not exotic: launch a browser, evaluate getComputedStyle over a set of selectors, cluster the results. What you would be rebuilding is the confidence scoring, the typography grouping, the spacing pattern detection and the token format exporters. Whether that is worth avoiding depends on how much you care about the DTCG output being valid, since the package exports a dtcg validate entry point rather than emitting free-form JSON.

Licence, maintenance and the cost of upgrading

Dembrandt is MIT licensed. That permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. It is a permissive licence with no copyleft obligation on your own code, and nothing in the project's documentation suggests a separate commercial tier gating the CLI or the MCP server. The hosted app at dembrandt.com/app is a separate surface and the README describes its local mode as requiring no login, with data staying in the browser; the cloud sync features are tied to a GitHub sign-in. Licence terms for the hosted service are not covered in the README, so read them separately if you plan to upload snapshots with --key.

On maintenance, the last push to the default branch was on 2026-09-10, and the most recent tagged release, v0.32.2, is dated the same day. Releases v0.32.1 and v0.32.0 landed on 2026-09-09 and 2026-09-08 respectively, so the project is shipping frequently. The repository is not archived. Note that package.json declares version 0.33.0 while the newest release listed is v0.32.2, which suggests the manifest is ahead of the last tag; if you pin a version in CI, pin the tag rather than trusting the manifest.

The upgrade cost is concentrated in one place: the GitHub Action reference. The README's example pins uses: dembrandt/[email protected], and the exit code table lives in docs/ci.md. Any change to exit codes or to the shape of the changes[] array in the JSON drift output would break a platform-neutral gate that parses it, so read docs/ci.md on each major bump. The token output itself is versioned by the DTCG format rather than by Dembrandt, which limits how much the exported file can churn.

Editorial conclusion

Adopt Dembrandt if you need a token set from a page you do not control, or a CI gate that fails when a preview deployment drifts from a committed baseline. Skip it for canvas or WebGL interfaces, since the README states there is no DOM to read, and for anything where you need hover and focus states captured from real interaction rather than from CSS. Before trusting a baseline, verify three things: that the target site renders without JavaScript errors under a headless browser, that you have run dembrandt install-browser on the machine or container that will do the extraction, and that the token categories you care about actually appear in the output rather than being empty arrays.

Frequently asked questions

How can I extract a DESIGN.md file from a website with Dembrandt?

Run the CLI with the --design-md flag, for example dembrandt dembrandt.com --design-md. The README lists this flag as producing a DESIGN.md file intended for AI agents. You still need to run dembrandt install-browser once beforehand, since the tool drives Chromium through playwright-core and ships no browser binaries.

Does Dembrandt need a browser installed separately?

Yes. The README states that playwright-core ships no browser binaries, so a fresh install has nothing to launch until you run dembrandt install-browser. Skipping that step fails with browser engine not available. Browsers land in a shared Playwright cache, so the step only needs doing once per machine.

Can Dembrandt analyze a site that renders with canvas or WebGL?

No. The README's limitations section states that canvas and WebGL-rendered sites cannot be analyzed because there is no DOM to read. The extraction depends on computed styles from the DOM, so an interface drawn entirely into a canvas element produces nothing useful.

How does Dembrandt fail a CI job when design tokens drift?

The platform-neutral form is dembrandt URL --compare baseline.json --json-only, which the README says exits 1 on drift and prints per-token changes[]. On GitHub you can instead use the Action with url and baseline inputs, which annotates the pull request with the drifted tokens. The exit code table is documented in docs/ci.md.

Official sources

  1. dembrandt/dembrandt on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dembrandt-dembrandt.svg)](https://hysenlabs.com/projects/dembrandt-dembrandt)