Skip to main content
Site

Process

Schemas before content

Why we write the Zod schema before we write the first paragraph — and how that one rule has saved us from years of cleanup work.

Editorial 4 min

There’s a rule on this team that we don’t break: no content type ships without a schema. Not a sketch. Not a “we’ll formalize it later.” A real Zod schema, in packages/schemas, validated by the Astro Content Layer at build time.

It sounds like overhead. In practice, it’s the single biggest reason our authoring experience stays calm as the catalog grows.

What goes wrong without a schema

Anyone who has worked on a marketing site for more than a year has seen this movie:

  • A field gets renamed in three posts and not the other forty.
  • A required image alt text quietly becomes optional because someone needed to ship.
  • A “tags” array starts holding strings, then objects, then strings with embedded JSON, then comments.
  • Templates end up wrapped in defensive null-checks that exist only to handle the drift.

The cost isn’t immediate. It compounds. By the time a refactor is justified, there are six contributors who all “know” the rules from memory, and none of those mental models agree.

What a schema gives us back

The schema is a single artifact that does five jobs at once:

  1. Type contract for every template that consumes the content.
  2. Validation gate at build time — broken frontmatter fails the build, never production.
  3. Documentation for human and AI authors alike. The schema is the spec.
  4. Refactor safety net. Renaming a field updates the type, which updates every template, which surfaces every callsite that needs attention.
  5. AI-friendly authoring substrate. Claude can read the schema, generate compliant frontmatter, and self-correct on validation errors.

A schema is the cheapest, most durable form of editorial leverage we’ve found.

The actual workflow

When we add a content type, the order is fixed:

  1. Write the Zod schema in packages/schemas/src/<type>.ts.
  2. Wire it into apps/<site>/src/content/config.ts as a collection.
  3. Build the template that renders it.
  4. Then author the first piece of content.

If step four reveals a missing field, we go back to step one. Authors are not allowed to add an undeclared frontmatter key as a workaround. That’s how drift starts.

The rule pays for itself within weeks

The first time someone tries to add a field that doesn’t exist and the build catches it before review, the rule has earned its keep. The second time the AI authoring assistant produces a perfectly-shaped post on the first try because the schema told it exactly what to write, the rule starts paying compound interest.

Schemas before content. Every time.

  • #zod
  • #content-modeling
  • #authoring