---
title: "Make the SEO contract a build gate — gCurv Technologies"
description: "Metadata regressions are silent. A build that fails on them turns a slow content problem into an immediate one."
lang: en
json-ld: |
  {
    "@context": "https://schema.org",
    "@type": "BlogPosting",
    "headline": "Make the SEO contract a build gate",
    "description": "Metadata regressions are silent. A build that fails on them turns a slow content problem into an immediate one.",
    "datePublished": "2026-08-24",
    "dateModified": "2026-08-24",
    "url": "https://gcurv.com/notes/make-the-seo-contract-a-build-gate",
    "author": {
      "@type": "Organization",
      "name": "gCurv Technologies",
      "url": "https://gcurv.com"
    },
    "publisher": {
      "@type": "Organization",
      "name": "gCurv Technologies",
      "url": "https://gcurv.com"
    }
  }
---

[![gCurv logo](/assets/gcurv-logo-CJpRRXOD.png)gCurv ](/)

[Work](/work)[Capabilities](/capabilities)[Products](/products)[Notes](/notes)[About](/about)

[Contact us](/contact)

Engineering note 

# Make the SEO contract a build gate

2026-08-24

Most site regressions announce themselves. A broken build fails, a broken test goes red, a runtime error throws. Metadata regressions do none of that. The page renders, the deploy succeeds, and the damage shows up weeks later in a traffic graph nobody can explain.

We shipped a framework migration that carried three of them at once. Every page emitted two title tags and two description tags, with a generic value first. Sitemap and RSS generators walked a build directory that no longer existed and quietly wrote empty files. A machine-readable content index crashed on a deleted module and produced nothing. All three published successfully.

The response was to make the contract executable. The production build now runs a metadata check and a full crawl of the built site, and fails if:

-   any page emits more than one title or description tag
-   a page that is linked internally is missing from the sitemap
-   a URL that should not exist returns anything other than 404
-   a page that should be indexable is marked noindex, or the reverse

## The subtle part is the exception handling

One of those rules initially failed on thirty-three pages that were deliberately set to noindex, follow and canonicalised to a hub page. They were linked internally and absent from the sitemap, which is correct behaviour for a consolidated page. The rule was right in general and wrong for that case, so the rule learned about indexability rather than being switched off.

That is the discipline worth keeping: when a gate fires on something legitimate, teach it the distinction. Disabling it costs you the next real regression.

We also keep a snapshot of the site's structure — page count, indexable count, sitemap entries, internal link totals — and diff it across large changes. A refactor that quietly drops two hundred internal links looks identical in a code review and obvious in a diff.

[← All notes](/notes)

![gCurv logo](/assets/gcurv-logo-CJpRRXOD.png)gCurv 

A full live website with homepage, platform narrative, product modules, services, pricing, and an editorial blog.

[Email our team](/contact)

### Platform

-   [Overview](/platform)
-   [Products](/products)
-   [Pricing](/pricing)

### Solutions

-   [Services](/services)
-   [Industries](/platform)
-   [Blog](/blog)

### Company

-   [About us](/about)
-   [Contact us](/contact)

© 2026 gCurv. All rights reserved. [Back to top ↑](#top)