SheetBuild · documentation
Gatenpm run verify · fails the build
Last runNo receipt in this build
Pairings56 gated · 10 decorative
Literals left43 · ratchet, down only
Documentation · last checked 25 September 2026
How this site is built, and what is actually unusual about it
Every portfolio tells you the person is thorough. You're meant to take that on trust, which is a strange ask from somebody whose whole job is checking things. So there's nothing below that isn't either a number you can reproduce or a source you can go and open. Including the bits where the evidence went against me.
Every portfolio says the person is thorough. This one is the working out.
SheetReceipt · the last run
CommitNone
TookNot run
After the buildoklch:check · bundle:check · can still stop the deploy
Receipt · none for this build
This build has no receipt.
Nothing ran the gates before this copy of the site was built, so there's nothing for this section to show you. On craighawkes.dev they run first, every time, and the run that passes is the one that writes this section.
Nobody typed this section. The run writes a receipt, the build reads it, and in Receipts mode you get every check by name with how long it took. Anything that reads the finished build runs once this page already exists, so it can't be listed here, and a failure there still stops the deploy.
Sheet01 · The short version
TierOne · the short version
Facts3 checkable
Sourcesrc/data/build-doc.ts
01 · The short version
What you are looking at
It's a portfolio that gates its own claims. Every number here is produced by something that runs, and when one of those fails the build fails with it. Sounds like a small distinction, and it's the whole distinction.
It's shaped that way because I spent eight months telling people a design system met a WCAG standard, then wrote the test that could actually check, and it hadn't. That's published here, in full, with the numbers. A portfolio that's already shown you the thing it got wrong is an easier one to believe about everything else.
- Nine gates run before anything ships, and two more once the build existsnpm run verify, then the build, then npm run verify:after-buildscripts/gates.json · vercel.json
- 66 accessibility tests across every route, at phone, tablet and desktop widthsnpx playwright test e2e/accessibility.spec.tse2e/accessibility.spec.ts
- 551 end to end tests over the whole sitenpm run test:e2ee2e/
Sheet02 · Measured, not asserted
TierOne · the short version
Facts3 checkable
Sourcesrc/data/build-doc.ts
02 · Measured, not asserted
Three things here that most sites do not do
Each one's checked against a survey of real sites rather than against a feeling I had. Two turned out rarer than I'd have guessed. One turned out to matter a good deal less than I'd assumed, and it's in here at the same size as the other two, because that's the point.
- The colour system is OKLCH, which 1.89% of sites useProject Wallace measured over 100,000 sites off the Majestic Million. Hex is on 97.10% of them. HSL on 6.20%. OKLCH on 1.89%. This site doesn't just author in OKLCH, it gates that the build hasn't quietly flattened the lot of it to sRGB on the way out, which isn't a hypothetical, it already happened here once and nothing said a word.projectwallace.com/the-css-selection/2026
- There is an llms.txt, which 5.61% of the top ten thousand sites haveCasey Burridge measured it against the HTTP Archive across twelve months, so the adoption figure is solid. Whether the thing works is a different question and the honest answer is nobody knows. No major AI provider has confirmed they read it. It stays because it costs a few kilobytes, not because I can show you it does anything. Cheap, and honest about being cheap enough to say so.caseyrb.com/blog/state-of-llms-txt-adoption
- Three separate builds, chosen by viewport, rather than one with media queriesPhone, tablet and desktop get different component trees, not one tree squeezed into three shapes. There's a real cost to that and it's written up below, because it's the reason a pair of accessibility defects sat here for months without anybody noticing.src/hooks/use-device-class.ts
Sheet03 · The gates
TierTwo · the detail
Facts4 checkable
Sourcesrc/data/build-doc.ts
03 · The gates
11 scripts that can fail the build
They're not linters: a linter tells you about the code. These check whether the things the site says about itself are still true, and every one of them was written after something got past me.
In August 2026 all nine that existed then got audited the only way a gate honestly can be: plant a violation of the exact thing it claims to catch, run it, and refuse to take a pass for an answer. Seven caught it straight away, two didn't, and why they didn't is the most useful paragraph on this page.
- check-contrast: every gated colour pairing, measured56 pairings, checked against WCAG ratios on every runscripts/check-contrast.mjs
- check-claims: the settled position on every assertion surfaceIt knows what's already been corrected once and fails the build if it creeps back in somewhere nobody was watching. Absolute money figures, the flat AAA claim, marketing absolutes, stale route counts.scripts/check-claims.mjs
- check-slop: the rate of the constructions models overuseIt measures rate rather than presence, against 22,234 words of my own writing. A device used once is a voice. Used every other sentence it's a tell.scripts/check-slop.mjs
- check-oklch: that the colour survived the buildReads the compiled CSS, not the source, because the source was never the problem. It needs the build to exist, so it runs straight after it, and a failure still stops the deploy.scripts/check-oklch.mjs
Sheet04 · The August 2026 audit
TierTwo · the detail
Facts3 checkable
Sourcesrc/data/build-doc.ts
04 · The August 2026 audit
What a full audit of this site found
Fifteen findings, nine fixed on the spot, and one of them withdrawn once I'd measured the thing properly instead of inferring it from the wrong place. The two worst were level A accessibility failures that had been live for months, and honestly the reason they were live is more interesting than the failures themselves.
Two rules inside the claims gate were dead, not wrong but dead. They'd got literal backspace characters sitting where regex word boundaries were meant to be, so each pattern was quietly demanding a control character that no real sentence has ever contained. A backspace doesn't show up in your editor, or your diff, or your terminal, or even in the regex printing its own source back at you. Reading that file for a week wouldn't have found it. Planting a violation and refusing to believe the pass did it in about a minute. That's the whole method.
Then the navigation, which is worse. Every link in the bottom bar had no accessible name at all below 768 pixels, because the icon was marked decorative, the full label was display:none, and somebody had marked the short label decorative as well. Nothing left. Six links with nothing for a screen reader to read out, and then the same six again in a second component that didn't share a line of code with the first.
The suite had never seen any of it, because the suite only ever ran at one width. On a site that renders three separate component trees, that means two thirds of the markup had never once been looked at by the thing whose entire job was looking at it. Four lines of config fixed that, and it failed on the very first run and handed me a second broken component in a file I'd already read twice and cleared.
- 7 of 9 gates caught a planted violation on the first passBoth misses were in the same gate, and neither was visible to readingdocumentation/audit/01-findings.md
- Two WCAG 2.2 level A failures, found and fixed2.4.4 Link Purpose and 4.1.2 Name, Role, Value, on the compact shell
- Three research figures withdrawn after checkingThe first draft cited a 55 second attention benchmark, a hiring statistic and a claim about AI crawlers. Not one of them survived being opened and read, and they're all still in the reference list under Rejected, with the reason each one failed.documentation/audit/REFERENCES.md
Sheet05 · What it costs
TierTwo · the detail
Facts0 checkable
Sourcesrc/data/build-doc.ts
05 · What it costs
The parts that are not free
Three component trees means three lots of CSS on every route. It was one stylesheet of 247 kilobytes when this was first written; split by route, the home page now delivers 69 kilobytes of it, measured on 24 September 2026. It also means the hydrated page ends up holding markup for shells you'll never see, though the server only ever sends one. I got that distinction wrong during the audit, wrote it down as a payload problem, then went and measured the raw HTML the server actually sends and found it wasn't one at all. Wrong, and left in.
Then the JavaScript. Every page makes you download between 196.3 and 200.8 kilobytes of it, compressed, before it does anything, and the privacy page, which has nothing interactive of its own, takes 196.3 of those. So the weight is React, Next.js and what every page shares, not any one page being greedy. Articles take 258.6, because they seat their own text on the baseline grid in your browser, with Quoin. Both are budgets now, 205 and 260, and a page that goes over fails the build. The script that measures it had a budget of 180 for the home page for weeks while the page weighed 197, because nothing ever ran it.
The gates take time to write and now and again they block something that's perfectly fine. That's why the claims gate carries an exemption list: a rule that can't tell a correction from a relapse is a rule that stops you writing about the correction at all, and the correction is the interesting part.
And there isn't a single unit test in this repository. Not one component in it is tested on its own. The end to end suite covers behaviour at the page level and covers it properly, but that's a narrower promise than the rest of this site makes, and it's fairer to say so plainly here than to let a test count in the hundreds sit on the page implying a kind of coverage that simply isn't underneath it.
The security headers are stricter than most production sites carry, and they still let inline scripts and inline styles run, which is the first thing anybody who reads a Content-Security-Policy will spot. The pages are built once, ahead of time, and Next.js ships each page's data as inline scripts. The proper fix is a nonce, a nonce has to change on every response, and that means rendering every page on request and giving up the static build the speed comes from. The inline styles are the same trade in miniature, a handful of values set on elements directly. On a site that took payments or held logins I'd pay for the nonce without thinking about it. This one holds neither, so I took the speed, and I'd rather you read that here than find it in the headers.
None of those headers reach you on this copy. It's the backup of the site on GitHub Pages, which serves the files as they are and can't add headers of its own, so the Content-Security-Policy and the rest are back as soon as the site returns to Vercel.
Sheet06 · Check it yourself
TierTwo · the detail
Facts7 checkable
Sourcesrc/data/build-doc.ts
06 · Check it yourself
Nothing here needs taking on trust
The repository behind this site is private, which sits badly on a page that keeps telling you to check things, so here's what you can check without it and how to get the rest. The contrast on any page with whatever checker you trust, llms.txt, and quoin.check() in the console on every route are all live on the site you're reading. The response headers aren't, on this copy, because it's the backup on GitHub Pages and can't send them. Two pieces of the source are public outright: Quoin's repository on GitHub, and the inclusive.io core as a package on npm.
If you want the gates themselves, ask for read access and you'll have it. Then clone it and run them. They'll either pass on your machine or they won't, and either answer's worth more than me telling you they do.
- Checkable from here, no access neededContrast · llms.txt · quoin.check() in the console
- Public on GitHubgithub.com/hawkbass/quoin
- Public on npm@hawkbass/inclusive-design-core, the inclusive.io core
- Every gate, in order, with read accessnpm run verify
- The gates plus the build plus every testnpm run verify:full
- Accessibility only, every routenpx playwright test e2e/accessibility.spec.ts
- The full audit, findings and referencesdocumentation/audit/