When you rebuild a site from a design, the parity gate checks the site still looks like it. It compares each page's text, fonts, colours and positions with a reading taken from the design.

1. Capture the design, once

Serve the design (any local web server will do), then:

bash
tools/droost/vendor/bin/droost-parity capture \
  --source http://localhost:5399 \
  --routes /,/about,/contact \
  --width 1280,390

This writes the reference to droost/parity/: every visible piece of text on each page, with its box and its look, at each width. Commit it.

Capturing is yours, before a run. During a run the reference is frozen, and the gate fails if it changes.

A static design's .html pages are captured at the path the site will answer: --routes /about.html is held against the site's /about.

2. Turn it on

yaml
gates:
  parity: { on: true, required: true, scope: frame, routes: "/", pages: "/" }
Option What it does
scope: frame judge only the header and footer (for the first tickets, before pages exist)
scope: page judge whole pages
pages: the pages to judge whole, at the first width, while the rest keep scope
routes: the pages built so far; the others are listed as "not judged" instead of failing
required: true a missing reference fails instead of passing with nothing measured

When you build a site in rungs, widen routes: and pages: as each page is built. droost workflow:intake routes <rung> prints the right routes: value for a rung.

3. What it reports

Each page passes or fails on seven checks. A failure names the check and the text it is about.

Check Asks
D1 Does the page load, without scrolling sideways?
D2 Is every text from the design there, in the same order?
D3 Is the type the same (face, size, weight)? Every heading must match.
D4 Are the colours the same?
D5 Does each text sit in the same place, within a tolerance?
D6 Does the header link to the same places?
D7 Do the header and footer look the same?

The verdict also says which site it judged and where the reference was read. A reference read on one platform is judged only on the same one, because browsers lay out the same page slightly differently.

Things the client changed

A design sometimes shows something the client decided against, or misses something the client added. Write the decision down in droost/parity/decided.json, citing the intake question that made it:

json
{
  "set_aside": [{ "route": "/about", "text": "Learn More", "decided": "Q6", "why": "the client dropped this link" }],
  "added": [{ "route": "/location", "text": "Times are shown in Chicago time.", "after": "Closed", "decided": "Q8", "why": "the client chose the dealership's clock" }]
}

An entry with no decision, or naming text the design does not show, is refused, so the file can only hold real decisions.

Text that changes by itself

Some text follows the clock: "Open now", "Friday · today". Capture reads such a page again with the clock moved, across every weekday, and leaves out whatever changes. The verdict lists those texts as "not judged".