Extract the contract
Point it at the page you are building toward. Nothing has to be approved first.
npx pixelpact extract \
https://reference.example.com \
--selector "main" \
-o contract.json
Visual contracts for the browser
pixelpact reads the reference page and writes down what it actually renders: sizes, colors, spacing, typography, hover and focus states, animation keyframes, design tokens. That file is the contract. Point pixelpact at your implementation and it answers with one line per property that drifted.
$ npx pixelpact extract https://reference.example.com -o contract.json
$ npx pixelpact check contract.json http://localhost:3000
A coding agent writes the CSS and says it is done. It never sees the result. Nothing hands it a number, so the loop cannot close: the agent guesses, you open the page, you send it back, it guesses again. Every round costs you the one thing the agent was supposed to save.
Point it at the page you are building toward. Nothing has to be approved first.
npx pixelpact extract \
https://reference.example.com \
--selector "main" \
-o contract.json
Every value in the contract is asserted against your implementation.
npx pixelpact check \
contract.json \
http://localhost:3000 \
--viewport desktop
Exit code 0 inside tolerance, 1 outside it. It drops straight into CI.
npx pixelpact side \
https://reference.example.com \
http://localhost:3000 \
--widths 1440,390
A real run against two copies of one page with four declarations changed.
pixelpact check FAILED
target http://localhost:4173/impl.html
reference http://localhost:4173/ref.html
viewport desktop 1440x900
elements 14 matched, 0 missing of 14
checks 1056 passed, 10 failed (99.1% of 1066)
deviations (10)
SELECTOR PROPERTY EXPECTED ACTUAL DIFF
body > main > h1 font-size 48px 44px 4px
body > main > a box.width 117.75px 109.75px 8px
body > main > a padding-right 24px 20px 4px
body > main > a padding-left 24px 20px 4px
body > main > a background-color rgb(11, 114, 133) rgb(37, 99, 235) 60.1 (color)
body > main > a border-top-left-radius 8px 4px 4px
body > main > a border-top-right-radius 8px 4px 4px
body > main > a border-bottom-left-ra... 8px 4px 4px
body > main > a border-bottom-right-r... 8px 4px 4px
body > main > a focus.outline rgb(11, 114, 133) s... rgb(37, 99, 235) so... differs
Run the same check against the reference itself and all 1066 assertions pass, which is the
property that matters: a passing check has to mean something. Add --json to get
the same report as a data structure, which is what CI jobs and agents read.
check says which values moved. diff says how many pixels moved.
side splits both pages into sections and shows you where to look.
# SECTION WIDTH VERDICT DIFF
01 hero 1440px PASS 0.000%
02 features 1440px FAIL 0.675%
03 pricing 1440px PASS 0.000%
04 foot 1440px FAIL 1.265%
An agent that writes UI code cannot tell whether it succeeded. pixelpact-mcp
gives it the measurement, so the loop closes without a person in the middle: extract the
contract once, then let the agent check its own work, read the deviation list, fix, and
check again.
Tools exposed:
extract_contract, check_implementation,
diff_pixels, read_contract_summary
// .mcp.json
{
"mcpServers": {
"pixelpact": {
"command": "npx",
"args": ["-y", "pixelpact-mcp"]
}
}
}
Percy, Chromatic, Applitools and BackstopJS compare your page against a baseline you approved earlier. While you are still building toward a design, there is no baseline.
| Comparison | Visual regression tools | pixelpact |
|---|---|---|
| Compares against | a snapshot you approved earlier | the reference design itself |
| Useful when | the UI is already correct | the UI is being built |
| First run on a new page | records, cannot judge | measures against the reference |
| Answer you get | an image diff to inspect by eye | a value per property, with a delta |
| Fits an autonomous agent | needs a human to approve the diff | the numbers close the loop |
The two models are complementary. Use a regression tool to keep a finished page finished, and pixelpact to get it finished in the first place.
Reads the page you are building toward and writes down every value it renders. Nothing to approve first.
Each deviation carries the expected value, the measured value and the difference between them.
Interactive elements are hovered and focused, and only the properties that actually change are stored.
Custom properties on the root element and named animation keyframes travel inside the contract.
When every value passes and it still looks wrong, compare the screenshots and get a percentage.
The contract is a file you can read, diff and review in a pull request. No service, nothing to log into.
A composite Action runs the check and keeps one comment on the pull request up to date.
It measures the rendered DOM, so React, Vue, Svelte and hand written HTML are all the same to it.
A Figma url is read through the REST API, and the contract binds to your markup by data-contract.
| Command | What it does |
|---|---|
pixelpact extract <url> | Reads the reference and writes a contract file |
pixelpact check <contract> <url> | Measures an implementation, prints deviations, sets exit code |
pixelpact diff <contract> <url> | Pixel comparison against the screenshot stored in the contract |
pixelpact side <reference> <url> | Section by section images with the differences boxed |
$ pnpm add -D pixelpact playwright
$ pnpm exec playwright install chromium
playwright is a peer dependency, so the browser download stays under your
control and a project that already has Playwright installs nothing extra.