Gerris home
Gerris

Chris Abraham: technical consulting, AI tools, and technical SEO

Home › Services › SEO Engineering

SEO engineering for sites built in code

A Next.js, React, or headless site has no SEO plugin. Every title, canonical tag, sitemap entry, robots rule, redirect, and block of structured data is produced by code in your repository. That makes search a software problem, and I treat it like one: I write the change on a branch, test it automatically, check it on a preview build, and recrawl after it ships.

Where the SEO lives in a modern codebase

Metadata in components

In the Next.js App Router, page titles, descriptions, canonical URLs, and robots directives come from a metadata export or a generateMetadata function in each layout or page. Next.js resolves both on the server and sends the tags in the HTML response. When metadata depends on request time data, Next.js can stream it into the page body for crawlers it expects to run JavaScript, so I check what each important crawler actually receives. I write those functions so each route builds its tags from its own data, with sensible fallbacks for the routes nobody thought about.

Sitemaps and robots rules generated by code

A sitemap typed by hand drifts away from the site within a month. I generate it from the same route and content data that builds the pages, so a page that exists is listed and a page that's gone disappears. Robots rules get the same treatment, including explicit decisions about AI crawlers such as GPTBot, ClaudeBot, and PerplexityBot.

Redirects in configuration

Redirect maps belong in the framework's configuration or the host's rules file, under version control, where a reviewer can read them and a test can exercise them. Migrations and URL changes become a reviewed file instead of a spreadsheet someone pastes into a dashboard.

Structured data built into components

JSON-LD for organizations, products, articles, breadcrumbs, and FAQs is assembled inside the components that render the visible content, from the same props. The schema can't disagree with the page, and every new page built from the component carries it automatically.

SEO regression checks on every build

This is the part most teams skip, and the part that keeps the work from quietly coming undone. Search problems are usually introduced by an ordinary change: a new layout that drops the canonical, a content import that blanks the descriptions, a component that adds a second H1. A test that runs on every build catches each of those before it reaches production.

This site is a working example. Its build script refuses to publish when any title falls outside 50 to 60 characters, any description falls outside 140 to 160, either one contains a pipe, a dash, or a hyphen, two pages share a title or a description, a page has more or fewer than one H1, a page falls under its minimum word count, an internal link points at a page that doesn't exist, or two pages share more than 15% of their six word phrases. I build the same kind of gate into client repositories, tuned to their templates: required tags per route, valid JSON-LD, sitemap and route agreement, and balanced HTML from the CMS.

Deploy previews checked before merge

Netlify and Vercel both build a preview deployment for each pull request, at its own URL, without touching production. Netlify also sends an X-Robots-Tag: noindex header on its previews, so they stay out of search results. That preview is where I check a change the way a crawler will see it: the rendered HTML, the head tags, the structured data, the status codes, and a small crawl of the affected templates. Your developer reviews the code, I review the search outcome, and the merge happens once both pass.

The branch and pull request workflow

Every change I make arrives as a branch with a pull request: one concern per pull request, a description that says what changed and why, the URLs to check, and the test that proves it works. Nothing goes to your main branch without your team's review. When the work is done, the history of every SEO decision lives in Git alongside the code it affected.

A recrawl after release

Once a change is live, I crawl the production site again and compare it with the crawl from before. Search Console's URL Inspection confirms what Google fetched. That closes the loop: the change was written, tested, previewed, reviewed, released, and verified on the live site.

How an engagement runs

  1. Access list. Read access to the repository, a Search Console user, and access to preview deployments. My guide to giving an outside SEO repository access safely covers the setup.
  2. Sprint. A fixed list of changes, agreed in writing, each delivered as a pull request with a regression check where one makes sense.
  3. Verification. A recrawl and a Search Console read after each release, and a short written summary of what changed on the live site.

Common questions

Which frameworks and hosts do you work with?

Next.js, React, Astro, and static site generators, with headless content from Sanity and similar systems, deployed on Vercel, Netlify, Cloudflare, or GitHub Pages.

Do I need to give you write access to the repository?

Read access is enough to start. Write access comes later, once branch rules require a reviewed pull request before anything merges to main.

Will the build checks slow down my developers?

Each check runs in seconds and fails with a plain message naming the page and the rule, so a developer can fix it on the spot.

Can you work alongside the developer or agency I already have?

Yes. I work through the same pull requests and reviews they already use, and I hand over the tests so they keep running after I leave.

Send me your repository and your search problem

Updated October 13, 2026