Compares a live page with its design element by element — computed CSS and geometry, not screenshots. A companion plugin reads the file from inside Figma: no REST API, no rate limits.
Solid oak, hand-finished in small batches. Delivered flat, assembled in minutes.
Browse the catalogueSolid oak, hand-finished in small batches. Delivered flat, assembled in minutes.
Browse the cataloguesnapshots/Every element is checked against its Figma node: typography, colours, spacing, size and position. Differences come back named, not as a percentage of pixels.
Computed CSS and geometry of each mapped element against the node in the snapshot. Per-property tolerances, per-node ignores.
The Figma plugin walks the file through the Plugin API and writes a JSON snapshot. No tokens, no 429s — works with any file you can open.
Desktop, tablet and phone through CDP device emulation. The browser window never resizes.
An MCP server exposes node styles, renders and the checker. Claude Code fixes CSS without a Figma tab.
npm run patch turns mismatches into a proposed patch you review before applying.
Rendered PNGs of design blocks laid pixel-aligned over the page. Drag the curtain: design on one side, the live page on the other — misalignments jump out.
A node ↔ selector map per page, shared blocks once. automap writes most of it; verify --fix catches selectors that stopped matching.
"hero/title": { "selector": ".hero h1" }, "hero/lead": { "selector": ".hero p", "tolerance": { "line-height": 0.05 } }, "hero/badge": { "skip": "rendered by JS" }, "@header": "_shared"
The snapshot is a plain JSON you can commit. CLI, browser panel and the MCP server all read the same file.
Select frames in Figma, press Capture — or export the whole project.
automap pairs nodes with selectors; the rest is a click.
hero/title↔.hero h1hero/cta↔.hero .btnCLI, browser panel or MCP — the same report.
An HTML page for people, JSON for agents, and a CSS patch proposal.
.hero h1font-size56px52px.hero .btnpadding14px 28px12px 24px.navgap32px24px.hero pcolor#a9b0bd#a9b0bd.hero pline-height1.551.55{
"page": "home", "viewport": "desktop", "status": "failed",
"diffs": [
{ "node": "hero/title", "selector": ".hero h1", "prop": "font-size", "figma": "56px", "actual": "52px" },
{ "node": "hero/cta", "selector": ".hero .btn", "prop": "padding", "figma": "14px 28px", "actual": "12px 24px" }
],
"matched": 41, "missing": [], "skipped": ["hero/badge"]
}/* pixel-guard patch · home @ desktop · review the cascade before applying */ .hero h1 { font-size: 56px; } /* was 52px */ .hero .btn { padding: 14px 28px; } /* was 12px 24px */ .nav { gap: 32px; } /* was 24px */
A heading rendered at 52px instead of 56px.
Node ≥ 20, Chrome, Figma desktop app for snapshots.
$ git clone https://github.com/PavelKhabusov/pixel-guard && cd pixel-guard $ npm install $ ./start.sh # Figma ↔ browser bridge + panel # Figma → Plugins → Development → Import plugin from manifest… → plugin/manifest.json # Chrome → chrome://extensions → Load unpacked → extension/