When a pipeline with an LLM writes content straight into your repository, the engineering question is not “what if the AI gets it wrong?” — it will get it wrong. The right question is: where is the error allowed to exist? This blog’s answer: the error may exist in the draft, in the Pull Request, in the preview — anywhere before production. Never after. That is not guaranteed by a well-written prompt; it is guaranteed by an executable contract.

This post describes Fluxonar’s content contract — a Zod schema that validates the frontmatter of each post at build time — and the real case from this week in which it blocked a mistake of mine, a human one, exactly as it would block the LLM’s.

The contract is an API, not a convention

The editorial pipeline planned for this blog would end with N8N writing a markdown file and opening a PR. Between what the LLM writes and what Astro accepts, there is a schema declared in code:

  • title: 10 to 70 characters — the practical display limit in a search result.
  • description: 50 to 160 characters — the meta description window.
  • category: a closed enum (tech, ia, automacao). There is no “new category” by accident.
  • tags: at most 6, and each one must exist in a versioned file (tags.json). The list is the single source; free text does not get in.
  • pubDate: a validated ISO date; draft: a boolean with a safe default.

Markdown that violates any rule fails the build. And because the preview deploy runs the build, the broken PR never produces an approvable preview — the error dies on the line, visible, with a message pointing at the field. Fail-closed: the path from the error to production does not exist by construction.

A prompt is not a guarantee. An executable contract is: the build refuses what the model invents outside what was agreed.

The real case: the tag that did not exist

While writing the previous post — me, a human, with review — I used three tags: cloudflare, dns, seo. The build failed immediately: dns does not exist in tags.json. That is not a bug; it is the design working. The taxonomy is deliberately closed: a new tag requires changing a versioned, protected file, which means it requires an explicit human decision — it never arises as an improvisation in the middle of a post.

Why this matters even more with an LLM in the loop: models love to invent taxonomy. Ask for ten posts and you get cloud, cloudflare, cdn, hospedagem — four labels for the same thing, and a tag file that turns into a landfill. With a closed enum, the model may suggest whatever it wants; the build only accepts the vocabulary people decided.

Why validate twice

A design detail that looks like redundancy and is not: validation exists at two points. The N8N validation node checks the frontmatter before writing the file (fast feedback, still inside the pipeline, where regenerating is cheap). The Astro schema checks again at build time (a hard guarantee, independent of who wrote it — pipeline, human, or script).

The first validation is convenience; the second is safety. If they diverge, convenience lies — which is why both run the same validation logic, extracted into a single module, with an automated test proving the parity. A general rule for any pipeline: the inner validation may be a copy of the outer one, never an interpretation of it.

The portable principle

None of this is specific to a blog or to Astro. The recipe, portable to any system in which an AI produces artifacts:

  1. Declare the contract in executable code (schema, types, enum) — not in a good-intentions document that nobody runs.
  2. Close the vocabularies. Everything that is a classification (category, tag, status, type) is a versioned enum, never free text from the model.
  3. Couple validation to the publication path. If it is possible to publish without passing through the contract, the contract is decorative.
  4. Let the error be cheap. A failure in a PR build costs one click to regenerate; a failure in production costs credibility — and, in the case of content, ranking.

The human gate decides whether the text deserves to go live. The contract guarantees that, technically, only what is already structurally correct reaches that decision. They are different layers — and it is the sum of the two that lets an AI pipeline operate without fear.