Engineering

Encode content governance as build gates, not as a style guide

Published

Most companies have a website copy standard. Do not overstate. Back every number with evidence. Do not describe a feature under development as if it already ships. The document is usually well written, then filed in shared storage, then bypassed in full during the next launch crunch.

The failure is not a lack of discipline. It is that a written standard executes only when somebody remembers to apply it. That is a process with no trigger.

Make non-compliant content fail the build

The rules for this site are encoded as build-time gates. Not lint warnings — errors that stop npm run build with a non-zero exit code. There are four layers, each responsible for something the others cannot see.

Schema, first. Every content type has a Zod schema. A missing field, an invalid enum value, or a violated custom rule fails while astro build is reading content. Product maturity and feature maturity, for instance, are two separate enums — so it is not typologically possible to mark a product still in development as generally available.

Cross-collection checks, second. A file can be individually valid and collectively wrong. Published content referencing an unapproved claim, a project missing its attribution type, a page declaring a relationship that does not exist — none of these are visible from a single file, so they live in a separate check that runs before the build.

Render guards, third. Even if an unapproved claim reaches the data layer, the rendering components exclude it. This layer exists as an admission that the first two might have holes. With a single line of defence, one hole is total.

Output verification, fourth. After the build, scan dist/ — no leaked secrets, no unexpected locale routes, every sitemap URL resolving to a page that actually exists. This layer does not verify what the source intended. It verifies what is about to be deployed.

Why it earns its cost

Because errors propagate, and they propagate faster than corrections do.

We hit this ourselves. One character of the company tax ID was wrong. It was not wrong in one place: that value is shared by structured data, the footer and the contact page, so a single mistake surfaced in close to a hundred public locations at once. By the time it was noticed it had already been built and deployed.

Fixing it took minutes. The real lesson was that a build gate asserting “the tax ID must pass its check-digit validation” would have made the incident impossible. That gate exists now.

A gate needs a declared escape hatch

A check that only ever blocks, with no way through, eventually gets switched off. This is close to a law.

So when our checks meet a case they cannot adjudicate, they neither pass it nor block it outright — they require the author to declare. If a paragraph in an article contains both a product name and a number, no program can tell whether that is a result we achieved or an industry-wide observation. The first needs evidence; the second does not. The build stops and asks the author to add an explicit line to the file’s frontmatter stating that the figure has been reviewed.

The distinction is subtle and it matters. A style guide asks “did you remember to check?” A build gate asks “did you declare that you checked?” The first cannot be audited. The second lives in version control.

This is not a complete solution

Automated checks catch structural errors. They do not catch tonal overstatement. “Years of deep industry experience” trips no rule, and may be just as imprecise.

What gates handle is the class of error a machine can adjudicate — which happens to be the class most likely to occur under deadline pressure, and most likely to carry real consequences. The rest still needs a human reader. But that reader can now spend their attention where judgment is actually required, instead of re-checking a field the computer should have caught.

Back to all insights