Skip to content

Quality

Auditing what the build renders

2 min readStatic Core

Every page exists as a string in memory the moment before it is written to disk. Reading it back to see what it claims about itself is close to free, and it catches the regressions that otherwise surface weeks later in somebody else's audit tool.

Dense, colour-coded source code filling an angled monitor.

Why the check belongs in the build

An external audit tool tells you about a page after it has shipped, one page at a time, usually in a report nobody opened. A build-time check tells you before it ships, about every page at once, in the terminal you are already looking at.

It also has information the external tool does not: it can see all twenty pages together, so it can say that two of them claim the same title, which is invisible to anything examining one page at a time.

This site sets the audit to strict, so an error-level finding fails the build. That is not perfectionism — the host builds straight from the default branch, so an audit that only reports means the broken page ships and the report scrolls past in a log.

The checks worth having

Not everything is worth automating. The checks that earn their place are the ones a person cannot hold in their head across a whole site: a title duplicated on two pages, an id used twice, a heading outline that skips from h1 to h3, a link whose only text is the word here.

Sixteen of them run on every page: missing titles, description length, a lang attribute on the html element, exactly one h1, images with no alt text, links with no accessible name, a link opening in a new tab without the rel attribute that protects the opener, and two elements both claiming to be the current page.

The parsing is regular expressions, which would be indefensible against markup from the internet and is fine here: it only ever reads markup this same build produced a millisecond earlier. Style and script bodies are stripped first, so an inlined stylesheet is never mistaken for markup.

The check that paid for the rest

One of them earned its keep the day it was written. Two elements on the same page both claimed to be the current page — the breadcrumb and the nav — and a screen reader announced whichever came first, which was the wrong one.

The nav should have been saying it was the current section, not the current page. That is a distinction nobody makes by hand consistently across a site, and a check that costs a millisecond makes it every time.

The fix was one component and one attribute value. Finding it without the check would have taken a bug report from someone who had already had the bad experience.

Key takeaways

  • The build already holds every page as a string; auditing it costs almost nothing
  • Automate the checks a person cannot hold in their head across a whole site
  • A report-only audit on a branch that deploys itself is a log entry, not a gate
Back to the blog