Next.js / Vercel
Make a Next.js app agent-ready: static files, route handlers, and OG metadata.
Next.js gives you typed APIs for every metadata signal AIScan looks at. App Router projects can move every fix from "a file you forgot to update" to "code reviewed in a PR".
Start at the platform guide index for other stacks, or compare this setup with the Replit guide when a project is Vite or Express instead of App Router. These fixes map to Content, Discoverability, Bot Access, and Capabilities checks.
Per-route metadata
Export metadata (or generateMetadata) per page and per layout:
// app/about/page.tsx
export const metadata = {
title: "About — Acme",
description: "How Acme came to be.",
alternates: { canonical: "https://acme.com/about" },
openGraph: {
title: "About — Acme",
description: "How Acme came to be.",
url: "https://acme.com/about",
type: "article",
},
};robots.ts / robots.txt
App Router supports a typed app/robots.ts that AIScan reads the same as a static file:
// app/robots.ts
import type { MetadataRoute } from "next";
export default function robots(): MetadataRoute.Robots {
return {
rules: [
{ userAgent: "*", allow: "/" },
{ userAgent: ["GPTBot", "ClaudeBot", "PerplexityBot", "Google-Extended"], allow: "/" },
],
sitemap: "https://acme.com/sitemap.xml",
};
}sitemap.ts
// app/sitemap.ts
import type { MetadataRoute } from "next";
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const posts = await getPosts();
return [
{ url: "https://acme.com/", changeFrequency: "weekly", priority: 1.0 },
...posts.map((p) => ({
url: `https://acme.com/blog/${p.slug}`,
lastModified: p.updatedAt,
})),
];
}Public & .well-known files
Drop llms.txt, CLAUDE.md, aiscan-skill.json, and any .well-known/* files into public/. Next.js serves them at the matching site path. For dynamic content (an MCP server card derived from your DB), expose a route handler at app/.well-known/mcp/server-card.json/route.ts that returns JSON.
Edge headers (Vercel)
Add a Link response header in middleware.ts or vercel.json:
// vercel.json
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Link", "value": "</.well-known/api-catalog>; rel=\"api-catalog\"" }
]
}
]
}Further reading
- How to serve text/markdown to AI agents on every stack
An AI agent that sends Accept: text/markdown gets your HTML unless the server answers differently. Check C1 grades that exact request, and no staticsite generator or Next.js app does it by default.…
- Content Signals in robots.txt: 117 of 799 Sites Declare One
Of 799 sites in our scan database on 2 November 2026, 117 serve a robots.txt with a ContentSignal line 14.6%. Among the 677 sites that serve a usable robots.txt at all, that is 17.3%. Another 682…
- Your robots.txt blocks everything by accident: find the leftover Disallow: / and stop it coming back
If your robots.txt says Useragent: followed by Disallow: /, every crawler that obeys the file is told to stay off your whole site. It takes one line to cause and about a minute to find, and Google's…
- Does robots.txt Need a Sitemap Line? 782 Sites Show What Happens
Of 782 sites in our scan database on 29 October 2026, 572 serve a robots.txt that declares a sitemap, 89 serve a robots.txt with no Sitemap line, and 121 fail the robots.txt check outright. Declaring…
- JSON-LD in Google Tag Manager is missing from your served HTML: test it and move it server-side
If your JSONLD is added by a Google Tag Manager Custom HTML tag, a plain HTTP fetch of your page contains zero schema blocks. Google can still read it, because Googlebot renders JavaScript. Crawlers…
- One h1, title, meta description and JSON-LD on Ghost, Lovable, Next.js, Replit, Webflow, Wix and WordPress
One page needs one <h1, a <title, a meta description and a JSONLD block, and AIScan check C3 structured HTML passes only when all four are in the HTML the server returns. Who writes each of the four…
- How Big Is an llms.txt? Size and Structure Across 779 Real Sites
Of the 779 sites in our scan database on 28 October 2026, 427 served an /llms.txt file that returned a 200, and the typical file that passes our check is small: a median of 4,403 bytes, with 80% of…
- Fix soft 404s on Astro, Docusaurus, Lovable, Next.js, Webflow and Wix
A soft 404 is a page that says "not found" while the status line says 200. On the six platforms below, the default behaviour ranges from a correct 404 with a deadend body Webflow, Wix, Docusaurus…