
Shipping an agent-built site to production without surprises
The agent is right that the site works, on its machine. Six checks for the gap between running and being live, including the environment variable that breaks every canonical.
An agent will tell you the site works, and it will be telling the truth about the machine it ran on. Production is a different machine, with different environment variables, a build step your dev server never performs, and a cache that outlives your session. Most of the defects we have shipped on agent-built sites were not coding errors at all. They were the gap between running and being live, and every one of them is preventable with a checklist.
Decide the deploy trigger before the first commit
There are two sane arrangements and one bad one. The sane arrangements are a push to the main branch deploying to production, or a push deploying to a preview with a manual promotion. The bad one is an agent running the deploy command directly, because then the thing that decides what is live is a sentence in a chat window rather than a commit you can point at. Wire the repository to the host, as Vercel's deployment docs and the Next.js deployment guide both describe, and let git be the trigger.
This also gives you the artefact that makes everything downstream possible. Every deploy has a commit, every commit has a diff, and when something breaks at four in the afternoon you can read what changed instead of reconstructing a conversation.
The environment variable that quietly breaks your canonicals
On a framework site, the absolute URLs in your metadata come from a base URL you set once, usually in an environment variable. Get it wrong and the pages still render, the build still passes, and every canonical tag and every social preview points at the wrong host. Nothing in your session will tell you, because locally the value is correct.
Check it on the deployed page, not in the file. Fetch the HTML of a production URL and read the canonical and the Open Graph tags that actually came back. While you are there, check a child route rather than the homepage: metadata merges from the parent in ways that silently keep the parent's URL, which is the trap this piece on metadata inheritance was written about. The framework's metadata reference documents the merge behaviour.
What the build catches, and what it never will
A production build is the best single check you have, and it is narrower than people assume. It catches type errors, missing imports, invalid data that your own validators reject, and routes that fail to render at all. It does not catch a page that renders the wrong content, a heading that is visually clipped, a link that points somewhere valid but wrong, or a date comparison that behaves differently in a different timezone.
That last one is worth a sentence of its own, because it bites statically built sites specifically. If your content has publication dates and you compare them against the current time, the comparison runs at build time on a server whose clock is in UTC. A post dated today publishes or does not publish depending on a timezone you never thought about. Ours is deliberately compared against UTC for exactly that reason.
Images: the cache outlives your session
If your host optimises images, it caches them by source path. Replace a file in place, keep the filename, and the old image keeps being served. Vercel's image optimisation docs describe the caching; the part that catches people is that it fails partially. Swap three images and one updates, which reads as a rendering bug rather than a cache, and sends you looking in the wrong place for an hour.
Two rules close it. Change the filename when you change the picture, and clear the local image cache before you judge a swap. Neither is clever; both are the difference between a ten-second fix and an afternoon.
The preview deploy is the review
A screenshot from a local dev server is weak evidence. It was taken before fonts settled, or in a renderer that does not composite the way a browser does, or at a viewport nobody uses. A preview deploy is the real thing at a real URL, which means you can fetch its HTML, run a page audit against it, and look at it in the browser your client will use.
The order that works for us is build locally, push to a preview, audit the preview, then promote. The audit is three fetches and one browser pass, and it catches the class of defect that no amount of local verification reaches. This is the same argument as the verification piece, applied to the one environment that counts.
Rollback is a feature, so use it
When a deploy is wrong, the instinct is to fix forward with the agent, in a hurry, on a live site. Do not. Promote the previous deploy, which takes seconds and costs nothing, then fix at normal speed. The reason this matters more on agent-built work than on hand-written work is that a hurried agent session makes larger changes than a hurried person does, so fixing forward under pressure is how one broken page becomes four.
The checklist, in order
| Check | Where it fails if you skip it |
|---|---|
| Production build passes locally | Types, data validation, routes that cannot render |
| Base URL set in the production environment | Every canonical and every share image |
| Canonical read from a deployed child route | Parent metadata inherited onto children |
| Changed images renamed, image cache cleared | Old pictures served from cache, partially |
| Audit run against the preview URL | Everything local verification cannot see |
| Rollback target known before promoting | The twenty minutes after a bad deploy |
None of this is exotic, and that is the point. The failure mode of agent-built sites is not sophisticated bugs. It is competent code deployed into an environment nobody checked, and six routine checks close almost all of it. If you want the gates automated rather than remembered, the hooks piece covers that, and the SEO checklist covers what to verify once the site is genuinely live. You can also see the sites we have shipped this way.

