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— generatesDESIGN.mdfor 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 files —
lib/extractors.js,lib/display.js,lib/pdf.js;lib/extractors.jsalone is 2129 lines. Hard to hold in one head; changes ripple widely. - High - Deep nesting —
lib/extractors.jsandlocal-ui/src/App.tsxhit indentation depth 7. Flatten with early returns. - High - Duplicated code —
mcp-hosted.jsandmcp-server.jsshare 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.