Verify everything against the production build (next build && next start, or the deployed site), never the dev server. For page content and headings, run /seo-auditor. Don't promise rankings; make indexing correct.
1. One origin
- Decide the production origin (e.g.
https://example.com) and put it in one config value. - In Next.js set
metadataBase: new URL(origin)in the root layout, so relative canonical and OG URLs resolve absolutely. - Grep the repo for
localhost, old domains, placeholder domains andhttp://. None may reach production metadata, sitemaps or JSON-LD. - Redirect the other variants (http → https, www ↔ apex) with a single 301 hop.
2. robots.txt
app/robots.tsreturning{ rules, sitemap }. Allow the site; disallow only what is genuinely not for search (iframe-only preview routes, internal tools, search-result URLs).- Never use robots.txt to remove a page from the index; that needs
noindexon a crawlable page. - Verify:
curl $ORIGIN/robots.txtshows the sitemap line with the absolute production URL.
3. Sitemap
app/sitemap.tsbuilt from the same data as the routes (the registry, the CMS, the database), so it can't drift.- Include only canonical, indexable, 200-status URLs. No query-string variants, no noindexed pages, no redirects.
- Verify: fetch every URL in the sitemap and assert 200 and that its canonical equals itself.
4. Canonicals and duplicates
- Every indexable page sets
alternates: { canonical: path }. - Filtered and sorted views (
?category=,?q=,?sort=) canonicalise to the unfiltered page, or are noindexed. - Preview, print and embed routes:
robots: { index: false }. - Trailing slashes and casing are consistent; duplicates 301 to one form.
5. Metadata on generated routes
- Use
generateMetadataon dynamic routes and build title, description and canonical from the item's own data. - Check uniqueness: extract
<title>and<meta name="description">from every built page and count duplicates. Zero duplicate titles is the target.
6. Social cards
- Open Graph
title,description,url,siteName,typeand an image of 1200×630 (app/opengraph-image.tsxwithnext/og), plustwitter: { card: "summary_large_image" }. - Verify the rendered
<meta property="og:image">is an absolute production URL and that the image returns 200 withcontent-type: image/png.
7. Structured data
- Add only what is true:
WebSiteandOrganizationon the home page,BreadcrumbListon nested pages, an item type that honestly fits (e.g.SoftwareSourceCode,CreativeWork,Article,Productonly if it's for sale). - Never invent ratings, reviews, prices or FAQ markup for content that isn't a visible FAQ.
- Render it as
<script type="application/ld+json">with<escaped. Verify by parsing every block from the built HTML withJSON.parseand checking required fields; then spot-check in a rich-results validator.
8. Rendering and status codes
- Important content is in the server-rendered HTML (
curlthe page and grep for theh1and body text). - Unknown slugs return a real 404 (
notFound()), not a 200 with an empty state. - Crawl internal links from the home page and report every non-200 and every redirect chain.
9. URL structure
- Lowercase, hyphenated, readable, stable:
/components/silk-field, not/c?id=42. Changing a URL needs a 301 from the old one.
Output
A checklist with pass/fail and evidence (the command and what it printed) for each section, then the fixes, then the same checklist re-run.