Building · Building this site
Ready is something you test
How source, candidate, preview, production, and scheduled checks became one progressive release system.
TL;DR A site is not ready because one test suite passed. Karl Conjecture now grows confidence in stages: fast source checks, a full audit of the exact candidate, trusted preview verification, exact-release validation, live smoke checks, and a recurring production audit.
The site already had several useful safeguards: a restrictive Content Security Policy, automated internal-link checking, production redirect checks, and a custom 404 that is tested at both root and nested paths. The remaining release audit asked a different question: do those pieces still work together in a real browser?
That matters because configuration is only intent. A security header can be correct in a file and absent from the deployed response. A skip link can exist but fail to move keyboard focus. A page can look fine at one width while overflowing on a phone. Metadata can be centralized in a layout and still render incorrectly on one route.
The browser audit now discovers every public HTML page in the completed build and checks it in desktop Chrome, mobile Chrome, and an iPhone-sized WebKit browser. It verifies accessible rendering, page structure, metadata, canonical URLs, responsive width, keyboard navigation, menu operation, and the special indexing behavior of the 404 page. The production health check separately inspects representative live responses for the expected security headers.
Validation is a sequence, not a pile of checks
A release crosses several boundaries: source becomes a built artifact, the artifact becomes a deployed preview, a merged commit becomes a production candidate, and that candidate becomes the live site. Running every test at every boundary would be slow without necessarily adding confidence. Running everything only once would leave important gaps.
The release process therefore grows its evidence in stages:
- Fast source validation checks types, unit and policy behavior, dependency risk, and whether the static site builds.
- Exact candidate validation opens every generated public route in desktop and mobile browsers and performs the full accessibility and rendering audit.
- Trusted preview verification deploys that exact candidate without exposing credentials to pull-request code, then checks the deployed preview’s headers, indexing policy, keyboard behavior, and 404 response.
- Exact release validation rebuilds and audits the merged commit on the main branch, then deploys the same audited artifact to production.
- Production verification runs a small, read-only smoke suite immediately after deployment, while a weekly full live audit looks for drift between releases.
The weekly run matters even when the repository has not changed. Certificates, DNS, redirects, CDN-provided headers, and hosting-platform behavior can drift independently of the site’s source. It is a deep regression audit, not an uptime alarm: frequent availability checks and alerts belong to an independent outside-in monitor.
The merge gate sits between preview verification and release validation. Passing automated checks does not merge the change; it makes the evidence available for human review of the preview.
The nitty-gritty (robots welcome)
Audit the artifact people will receive
The tests run after Astro builds the site. Public routes are discovered from the generated files rather than maintained in a second handwritten route list. Each route is opened in desktop Chromium, Pixel 7 mobile Chromium, and iPhone 15 mobile WebKit, then checked with axe-core. Those are representative browser engines and layout widths, not a claim that an emulator replaces physical-device testing.
The audit also checks requirements that are easy to miss in a generic scan:
- exactly one main landmark and one level-one heading;
- a nonempty title and description;
- a canonical URL matching the rendered route;
- no horizontal overflow at either viewport;
- keyboard access to the skip link and primary menu;
- no canonical URL and explicit
noindex, nofollowon the 404 response.
The skip-link test exposed a small but real detail: its target needed to be programmatically focusable. The main landmark now has tabindex="-1", allowing keyboard activation of “Skip to content” to move focus to the content rather than merely changing the scroll position.
Verify deployment, not just configuration
The repository already tests the contents of its Cloudflare _headers file. The live health checker now supports exact, required-fragment, and forbidden-fragment header expectations. Representative 200 and 404 responses must return the expected Content Security Policy, Permissions Policy, Referrer Policy, HSTS policy, and MIME-sniffing protection.
This keeps two complementary tests:
- the source test explains what the policy is supposed to be;
- the production test proves that visitors actually receive it.
Keep credentials on the trusted side
The preview artifact is built and audited in the pull-request workflow without deployment credentials. A separate deployment workflow uses trusted configuration from the main branch, verifies the artifact, and receives narrowly scoped Cloudflare credentials only for the upload step. It never checks out or executes pull-request code.
That split is more than workflow tidiness. A preview should test untrusted changes without giving those changes a path to deployment secrets.
Keep the gate proportional
The full browser audit runs against the candidate before deployment. Preview and production then use smaller smoke suites to verify the environment boundary, and the weekly production audit repeats the deeper read-only checks against the live site. This keeps pull requests useful without pretending that a local build proves DNS, redirects, certificates, or response headers.
Automated accessibility checks do not certify that a site is universally usable. They are a regression gate for mechanically detectable failures. Keyboard behavior, mobile layout, and the actual content still need human review. The useful standard is not “the tool found nothing, therefore perfect.” It is “known checks pass, remaining judgment is explicit, and the next change has to preserve the baseline.”