Skip to content
Start
Internal tool

Loupe

Automated checking tools sometimes report that a page is fine when it isn't. Loupe is our own checking browser: it only reports what it actually measured on the real page, so problems don't slip through.

A browser that only reports what it actually measured.

This one is private, so we can't link to it here.

26

Tools in the server

2.5k

Lines, over Playwright

5,319:1

Control separation on the dither metric

0

Verdicts issued over unmeasured pages

01 FM · The problem

Why we built it.

When we checked designs through a normal automated browser, it kept failing in the worst possible way: it reported success. A window resize would say it applied 390px and deliver 1024. Device emulation and automation fought over one debugger socket. Contrast checks read colors from the DOM and returned confident, plausible, wrong numbers whenever text sat on a photograph, a gradient, or a translucent layer.

Each of these produced a green result instead of an error, and that's far more expensive. A wrong number that looks right gets believed and built on, and a person catches it much later, if at all.

The libraries themselves work as designed. They hand you a browser and a screenshot function, and they leave it to you to decide whether what you measured is true. That judgment was the missing piece, so we built it.

02 FM · The approach

The decisions we made, and why.

This part gets into the technical detail. If that isn't your thing, the short version is at the top of the page.

01

We applied one rule everywhere

Every answer comes from pixels. A tool reports what it measured afterwards, never what it was asked to do. `viewport` applies the emulation, re-measures the result, and stops with an error if the width doesn't match the request. A success is itself a measurement, which removes the whole class of failure where a tool reports an intention as an outcome.

02

We read contrast from the rendered image, not the DOM

DOM-based contrast checkers guess at the background, and they guess wrong on photographs, gradients, blends, and overlaps. Loupe screenshots the element, screenshots it again with the text made transparent, and compares the two. The pixels that changed are the text, and the second image holds the true background behind each one. The browser has already solved the hard problem, so Loupe reads its answer. Text that turns out to be covered reports `notVisible` rather than an invented ratio.

03

We grade only pages that can be graded

An error page, a login wall, or a near-empty document passes every accessibility check trivially. Four green verdicts over zero elements is exactly the confident but meaningless report Loupe exists to prevent. So it checks that the page is real first, and returns `blocked` rather than a clean bill of health. A check that examined nothing reports `unmeasured` rather than `pass`.

04

We built on Playwright rather than around it

Loupe uses Playwright to drive its own Chromium. What we added is the measurement discipline on top: confirmation that emulation took effect, pixel-derived contrast, session isolation so parallel callers keep to their own pages, and results that always come from a measurement. That's roughly 2,500 lines, over a library that does the heavy lifting.

03 FM · What testing found

What we only learned by testing.

Every item below is a real problem we found by measuring, and each one has a fix behind it. We share them because they tell you more about how we work than the features do.

01

A shared browser served a competitor's site for most of a session

We found this when a blind session used the tools on live client work. Callers shared one page object, so `shot` could return a screenshot of an entirely different site that looked like a normal result. We fixed it with per-caller session isolation and a guard that confirms the page is still the one you opened before any measurement runs. That guard has since caught legitimate navigations too: while capturing Kern, it stopped because a click had rewritten the URL to a permalink.

02

It reported success on an empty page

A Wayback frameset returned a nearly empty document, and it passed. That's why we added the sanity gate: the tool now states what it found, including character count, element count, and HTTP status, and declines to grade an empty page.

03

The audit measured a defect and then threw it away

The overflow check returned two things: a page-level flag for sideways scroll, and a list of every element hanging past the viewport edge. The combined audit read only the flag. Since `body { overflow-x: hidden }` is on nearly every site, a clipped element leaves the document the same width, so the flag stayed false. A hero graphic ending 340px outside the frame produced the verdict "Does it fit the screen? mobile ok, desktop ok". The data was there, and the audit dropped it one line before using it.

04

We tested the fix for silence as well as for noise

Flagging every element past the edge would have made the check useless, because off-canvas drawers, screen-reader text, and carousel slides belong there. So only elements that straddle an edge count, and anything inside a horizontal scroller is excluded. The test fixture carries two real defects and five patterns that must stay quiet, and the assertions cover both. A check that cries wolf gets ignored, which is the same failure we were fixing.

05

We validated a detector against known controls before trusting it

A dither detector reported that a site's images weren't dithered. Without a positive control, "nothing to detect" and "the detector is broken" look identical, so we generated both: a real Bayer-dithered gradient and a smooth one. The metric separated them by three orders of magnitude, 5,319 against null. Only then could we trust the negative result, and it turned out to be the important finding on that job.

06

The instrument was measuring its own smoothing

At first, that same detector scaled every image down before analyzing it, which averages a one-bit dither back into smooth gray. It was measuring its own smoothing and concluding, reasonably and wrongly, that the images were smooth. We fixed it to sample at native resolution. The negative result held after the fix, which is what made it a finding rather than an artifact.

04 FM · Built with

Built with, and still open

  • Node
  • Playwright
  • Model Context Protocol
  • pngjs
Still open
  • Content that escapes its container with `overflow: visible` and stops exactly on the viewport edge is neither a clip nor a page scroll, so Loupe can't flag it yet. We found this on our own site, by measuring after a screenshot looked wrong.
  • Composition, whether elements collide, and whether a design holds together are still beyond what these checks can see. The instrument raises the floor, and we still look at every page ourselves.