Set the web standards as data and check every build against them
Context and Problem Statement
Of the five real sites, three declare hreflang (one always pointing at the home pages), four a canonical, two a sitemap, two structured data, one a skip link; one has no focus styles, one loads fonts from Google, two load a reCAPTCHA script; three keep partial checkers of their own (i18n parity, contrast, dead links); none has continuous integration, an accessibility tool or Intl formatting. All five keep Spanish at the root and only one translates slugs, and even it keeps Spanish for its legal and thank-you pages in every language. What quality bar does every site meet, and how is it checked rather than hoped for?
Decision Drivers
Criteria 1 (trust), 4 (accessibility, WCAG 2.2 AA), 7 (three languages) and 9 (generated and tested) of ADR-0009.
Considered Options
- The standards as data (
brand/standards.yaml) and a checker that runs them, with the anatomy’s patterns, over any built site; this site the first to pass - A browser-based audit (axe, Lighthouse) run by hand before each deploy
- A written standard with no automated check
Decision Outcome
Proposed: the first option. brand/src/check-site.ts reads standards.yaml and
anatomy.yaml, walks a built site’s HTML and lists every violation; pnpm check runs it over
this site’s dist/ and fails the build on one. Running it on this site found 984 violations
and caused the fixes below; it now passes 26 rules over 175 pages with none.
- Accessibility. WCAG 2.2 AA is the floor. Checked statically:
langonhtmlequal to the page’s locale; exactly oneh1and no skipped heading level; exactly onemainand a skip link to it;alton every image; a name (role="img"and a title or label) oraria-hiddenon every inline SVG; text or a label on every link, no bare#; a label andautocompleteon every form control. Focus (--focus-ring), target size (24 px, controls 44 px) and reduced motion are the shape tokens’ job (ADR-0021); contrast is proven by the colour build (ADR-0015). Keyboard operation, zoom to 400 % and error announcement stay manual and are checked on each shared component when it is built. - Addresses and languages. Every page under its language (
/es/,/en/,/pt/), every segment translated, lowercase ASCII with hyphens and a trailing slash; the root redirects byAccept-Languagewith Spanish as the fallback (this site’s Worker already does),x-defaultpoints at the root; old addresses redirect permanently.hreflangfor the three languages plusx-default, absolute, the page itself included; acanonicalthat is the page’s own address. Numbers, dates and units throughIntlin the page’s language (es-AR, pt-BR, en). - SEO on indexable sites: title 10 to 70 characters, description 30 to 160,
og:title,og:description,og:url,og:image(the brand’s profile picture at 1200 px unless the page has its own),OrganizationJSON-LD on the home page naming AKRIBIS Group asparentOrganization, a sitemap with every page. Brand isnoindexwhile it is a draft and carries all of it but the sitemap; its home page’s JSON-LD lists the nine units and AKRIBIS One from the register. - Budgets per page, uncompressed: HTML 200 kB, CSS 80 kB, JS 150 kB, fonts 260 kB, at most
three preloaded fonts; width and height on every image; fonts from Brand only, never from a
font CDN. On this site the budget turned the inlined study sheets and marks into files: the
Colour page fell from 656 kB to under 200 kB, the 429-row download list became the SVG masters
with a pointer to
manifest.json. - Consent. No third-party script before consent; a script from an analytics or
advertising host must be gated (
data-consent). The default is none: where nothing tracks, no cookie notice. Cloudflare’s cookieless beacon is the one analytics allowed without it. - The checker.
node brand/src/check-site.ts <dist> --kind <unit|parent|one>prints every violation grouped by rule, the budgets of the largest page, and exits with an error; it readsstandards.yamlor a site’s own copy./standards.jsonand/anatomy.jsonpublish the rules for any tool. Every site runs it before deploying; this repository runs it inpnpm check.
Consequences
- Good, because the standard is the test: a page that skips a heading level or loads a font from a CDN fails the build instead of a review.
- Good, because the same rules, as data, serve twelve sites and an agent reading
llms.txt. - What a browser sees (computed contrast, focus order, keyboard traps) is not checked here; browser-based checks come with continuous integration, which no site has yet.
- Open: image formats and the LCP’s size; the redirect tables that move the sites’ current addresses to the grammar.