The Problem

Design systems are usually reverse-engineered by hand: opening DevTools, inspecting computed styles, and manually transcribing values into tokens. That process is slow, inconsistent across pages, and goes stale the moment the site changes. Teams need a fast, repeatable way to capture what a site actually renders, not what its CSS variables claim.

What This Does

dembrandt is a CLI and MCP server that crawls a URL, inspects rendered styles, and outputs design tokens: colors, typography, spacing, borders, shadows, and component styles. The core logic lives in lib/extractors.js (the extractBranding function) and lib/colors.js (color math like hexToRgb, deltaE). Output goes to the terminal via lib/display.js, to JSON, or to a W3C DTCG format via lib/w3c-exporter.js.

It also ships a local web UI (local-ui/) built with React and Vite, plus two MCP server entry points (mcp-server.js, mcp-hosted.js) for AI agents. The test/qa.mjs file contains a QA harness with golden-file comparison.

How It Is Wired

Execution starts in main at test/qa.mjs:381. The traced path is main -> extractSite which writes files via fs.writeFileSync. This is the only mapped path that leaves the process; the CLI's real browser automation (via Playwright) is not visible in the static call graph because it goes through framework callbacks.

The module graph has no cycles, but there is a clear hub: lib/colors.js is imported by 6 files, and lib/extractors.js is imported by 2. The highest blast radius is hexToRgb (called from 9 places) and hex (7 places) — both in lib/colors.js. Changing these ripples across most of the codebase.

File-by-file map:

  • lib/extractors.js — the extraction engine (extractBranding, extractSiteName); 31 functions, the largest file.
  • lib/colors.js — color conversion and distance math; 16 functions, the most imported.
  • lib/pdf.js — brand guide PDF generation; 20 functions.
  • lib/display.js — terminal rendering (terminalLink, displayResults).
  • lib/merger.js — merges multi-page extraction results.
  • lib/discovery.js — page discovery from DOM links or sitemap.
  • lib/design-md.js — generates DESIGN.md for AI agents.
  • mcp-server.js / mcp-hosted.js — MCP protocol implementations.
  • lib/w3c-exporter.js — DTCG token export.

How To Use It

npm install -g dembrandt
dembrandt example.com
dembrandt example.com --save-output
dembrandt example.com --dtcg
dembrandt example.com --pages 5 --sitemap

Requires Node.js 18+. For AI agents, register the MCP server:

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

Real-World Use

A design system team auditing a competitor's site runs dembrandt competitor.com --pages 10 --sitemap --save-output. The JSON output feeds into their token pipeline, and the DTCG export imports directly into Figma or Style Dictionary. The --brand-guide flag produces a PDF for stakeholder review.

Code Health & Issues

Static analysis (measured, not opinion) found 12 issues across 4 kinds:

  • High - Oversized fileslib/extractors.js, lib/display.js, lib/pdf.js; lib/extractors.js alone is 2129 lines. Hard to hold in one head; changes ripple widely.
  • High - Deep nestinglib/extractors.js and local-ui/src/App.tsx hit indentation depth 7. Flatten with early returns.
  • High - Duplicated codemcp-hosted.js and mcp-server.js share 29 repeated 6-line blocks. Extract shared helpers.
  • Medium - High branching density — 749 branch points over 2129 lines in lib/extractors.js, lib/design-md.js, lib/display.js. Consider table-driven dispatch.

SDLC observations: tests exist (test/qa.mjs) but there is no CI pipeline. Dependencies are stale — commander is 4 major versions behind, typescript 2 behind. License and lockfiles are present; no secrets found.

The Bottom Line

A genuinely useful tool that solves a real problem — extracting design tokens from live sites in seconds. The architecture is sound (no cycles, clear module boundaries), but the core extraction files are overdue for a refactor. Worth using as-is; worth cleaning up before you extend it.