Quality · checks

The checks behind the site.

The public site is small, but the deployment path still has real checks: static analysis, content checks, CSP generation, build validation, size budgets, Lighthouse gates, and CloudFront deployment through infrastructure as code.

Primary gate npm run check package.json 16 chained checks in CI-equivalent order.
Validated routes 21 scripts/validate-build.js Every expected HTML route must exist before deploy.
Required assets 19 scripts/validate-build.js Static files, generated metadata, camo tiles, and JS bundles.
Asset budgets 7 .size-limit.json Brotli-transfer limits for shipped JS and core imagery.
Brand system /brand/ website/_data/brand.js Palette documentation is generated from the live CSS tokens.

Latest local build artifact

These numbers are written into the built page after `_site/` exists, so they come from the generated artifact instead of hand-maintained copy.

  • HTML routes21 built / 21 requiredCounted from website/_site after build.
  • Output files48Every generated file under website/_site.
  • Output size1.32 MBRaw on-disk artifact size before CDN compression.
  • CSP hashes5 script / 21 styleParsed from the generated _site/.csp.txt.
  • CSP length1715 bytesFull policy value passed into CloudFormation.

Static checks

Source files are linted before any generated output is trusted.

JavaScript
npm run lint:js Biome checks source modules, build scripts, and formatting. biome.json
CSS
npm run lint:css + npm run lint:css:units Stylelint plus a PostCSS guard for invalid unit spacing. .stylelintrc.json
Markdown
npm run lint:md Project docs are linted without forcing Liquid page bodies into plain Markdown. .markdownlintignore
Spelling
npm run check:spell Cspell scans source copy, templates, CSS, JS, and scripts. cspell.json
Dead code
npm run check:dead Knip walks the local JS graph and dependency declarations. knip.json
Actions
npm run lint:actions Workflow syntax, action inputs, and expressions are checked before merge. scripts/lint-actions.js

Build integrity

The generated site has to be complete before Lighthouse or deploy runs.

Build
npm run build:silent Eleventy renders the site, JS is minified, CSP is generated, and quality artifacts are enriched. package.json
CSP
node scripts/build-csp.js Inline scripts and per-page inline styles are hashed from built HTML. scripts/build-csp.js
Output
npm run validate 21 pages and 19 assets are asserted from the build output. scripts/validate-build.js
HTML
npm run check:html Built pages are parsed after templating, PurgeCSS, and HTML minification. HTML validate config
Brand
npm run check:brand Canonical colors are locked so readability work cannot drift the palette off-brand. scripts/check-brand-tokens.js
A11y
npm run check:a11y 21 public and hidden routes are swept with axe-core after the production build. scripts/check-a11y.js
Visual contrast
npm run check:visual-contrast Chrome screenshots are sampled for text over camo, watermark, and cursor-reveal states. scripts/check-visual-contrast.js
Links
npm run check:links Internal and allowed external links are checked from the generated site. .linkinator.config.json
Budgets
npm run check:size 7 compressed asset budgets catch quiet payload drift. .size-limit.json

Lighthouse coverage

Desktop gates block regressions; mobile gates keep slower-device tradeoffs visible.

Desktop
npm run lighthouse 10 routes × 2 runs; performance, accessibility, best practices, and SEO are enforced. .lighthouserc.json
Mobile
npm run lighthouse:mobile 10 routes × 2 runs; accessibility and SEO are strict, performance is warn-only. .lighthouserc.mobile.json
Viewport smoke
browser QA after visual changes Phone, tablet, and desktop widths are checked against production builds. AGENTS.md
Motion preferences
browser QA after motion changes Reduced-motion behavior is checked when transitions or animation rules change. DESIGN.md

Security posture

The static deploy path still gets production-style controls.

Headers
template.yaml CloudFront sets CSP, HSTS, COOP, CORP, permissions policy, and referrer policy. template.yaml
CSP drift
npm run check:csp:prod A scheduled workflow verifies live HTML is allowed by the served CSP. .github/workflows/csp-check.yml
Audit
npm run audit High-severity npm advisories block the normal check pipeline. package.json
Deploy
.github/workflows/main.yml Only pushes to master deploy through CloudFormation, S3, and CloudFront. .github/workflows/main.yml

Lighthouse thresholds

Read from the two Lighthouse CI config files.

Desktop .lighthouserc.json

Performance
error ≥ 0.95
Accessibility
error ≥ 0.95
Best practices
error ≥ 0.95
SEO
error ≥ 1
CLS
error ≤ 0.05
LCP
warn ≤ 2500
Byte weight
warn ≤ 350000

Mobile .lighthouserc.mobile.json

Performance
warn ≥ 0.85
Accessibility
error ≥ 1
Best practices
warn ≥ 1
SEO
error ≥ 1
CLS
warn ≤ 0.05
LCP
warn ≤ 2500
Byte weight
warn ≤ 250000

Size budgets

Read from .size-limit.json.

site.js (orchestrator)
1 KB website/_site/js/site.js
router.js (same-doc nav)
4 KB website/_site/js/router.js
modules/* (lifecycle JS)
6 KB website/_site/js/modules/*.js
all JS (every visitor downloads)
10 KB website/_site/js/site.js, website/_site/js/router.js, website/_site/js/modules/*.js
OG card
85 KB website/_site/og-default.jpg
camo + monogram (raster atlas)
140 KB website/_site/camo/*.webp, website/_site/monogram.webp
font subsets (all shipped faces)
140 KB website/_site/fonts/**/*-site.woff2

Next gates worth adding

  • Add Playwright visual snapshots for home, notes, fit pages, work pages, and this dashboard.
  • Add scripted keyboard and screen-reader smoke checks for the primary navigation paths.
  • Publish a CI run artifact that records the latest branch, commit, and check URL for this page.
  • Add structured-data validation for Person, ProfilePage, and future Article pages.