DEV Community

Test Page for Printer
Test Page for Printer

Posted on

One layout file, three outputs: building printer test pages as real CMYK PDFs with Astro

I built testpageforprinter.com, a free set of printer test sheets (color, black and white, CMYK, alignment, nozzle check, scale, photo, duplex). Most "printer test page" sites hand you one generic image. I wanted sheets that really are what they claim to be: vector, in the right color space, at the right size. This post covers the part I found most interesting to build.

The problem with "just print this image"

A test page that goes through a browser print dialog can quietly be wrong in three ways:

  • the page is scaled ("Fit to page"), so an alignment test lies to you;
  • colors are converted to RGB, so a "CMYK" test is not testing the cyan, magenta, yellow and black channels separately;
  • Letter and A4 are different sizes, and a file made for one gets shrunk onto the other. An A4 sheet on Letter paper prints at about 94%, and a Letter sheet on A4 at about 97%.

One geometry, three renderers

Each sheet is described once, in millimetres, in a single file (layouts.mjs). Three small renderers consume that description:

  1. pdf.mjs writes a real PDF with pdf-lib. Fills and strokes use DeviceCMYK operators, and the font is embedded (the standard-14 Helvetica is not embedded, so I bundle Inter at build time).
  2. svg.mjs produces the SVG used for the in-browser print layout, with a static @page size and print-color-adjust: exact.
  3. The same SVG path, rasterized from the real PDF with Poppler, gives the preview images on the pages.

Because the previews are rendered from the real PDFs, what you see on screen is what prints. Every element sets an explicit color, so a CMYK sheet never contains a stray RGB operator. A build step verifies all 20 PDFs (Letter and A4 for each sheet).

// layouts.mjs, simplified: one description, coordinates in mm
s.qr(MG, fy, 18, `${site.url}/result/${o.id}/`);
s.text(MG + 22, fy + 14.5, 'Print at 100% (Actual size). Turn “Fit to page” off.');
Enter fullscreen mode Exit fullscreen mode

The scale check is just arithmetic, so it is testable

Print the scale sheet, measure its 100 mm bar, type the length in. The diagnosis is a pure function with no DOM:

const A4_ON_LETTER = (279.4 / 297) * 100; // 94.07
const LETTER_ON_A4 = (210 / 215.9) * 100; // 97.27
Enter fullscreen mode Exit fullscreen mode

If the measured scale is within a small tolerance of one of those two numbers, the tool says the paper sizes are mismatched; otherwise it points at "Fit to page" or a custom scale. Pure functions meant I could unit test it with the Node test runner and no browser.

QR codes on the sheet read the result

Every sheet carries a QR code that opens a "read your result" page with permalink hashes, so someone can scan the printout and walk through what they see. Only hashes that match a known option are applied, and nothing user-supplied is injected into the HTML.

What is not finished (honestly)

  • A camera-based nozzle check exists but is tuned only on synthetic photos, because I have not collected real phone photos of real printouts yet. It is labelled beta.
  • The defect photos on the site are AI-generated placeholders and are tagged "Illustration" until I replace them with real ones.
  • I have not tested printing on a range of real printers; the site says so.

Stack

Astro (static output), Tailwind, pdf-lib, qrcode, Playwright for QA screenshots, and Node's built-in test runner. Lighthouse on a local preview scored 94 to 99 for performance and 100 for accessibility and SEO on the pages I measured; real-host numbers still need re-measuring.

If you print test pages for a living, or have a printer that misbehaves in interesting ways, I would like to hear what the sheets miss: testpageforprinter.com. I built it, so this is my own project.

Top comments (0)