Guide · Next.js 1612 Aug 2026 · 11 min

Next.js agent-ready: minimal recipe

The minimal recipe that doesn't break the Docker build and makes your Next.js agent-ready (n=1, 6 weeks, no citation guarantee).

Minimal recipe — 4 steps that don't break the build

Based on the real belmon.tech case (6 weeks, 0 extra deps). Covers AR-DISC-01/05 + AR-CONT-01/02 and the Next 16/Turbopack gotchas that almost break the Docker build due to leads_db.

1 · DB sin romper el build

// app/readiness/[lang]/page.tsx  (o cualquier page que lea DB)
import { connection } from "next/server";
import { Suspense } from "react";
import { getAllPlans } from "@/app/lib/plans";

export default async function Page() {
  await connection(); // difiere a request-time, clave en Docker sin leads_db
  return (
    <Suspense fallback={<p>Cargando planes…</p>}>
      <PlansList /> {/* dentro hace await getAllPlans() */}
    </Suspense>
  );
}
// Nunca uses export const dynamic = 'force-static' si lees searchParams o DB

2 · Link headers sin HTML

// next.config.ts
export const linkHeaders = async () => [
  {
    source: "/(.*)",
    headers: [
      { key: "Link", value: '</sitemap.xml>; rel="sitemap"' },
      { key: "Link", value: '</llms.txt>; rel="describedby"; type="text/plain"' },
      { key: "Link", value: '</.well-known/api-catalog>; rel="api-catalog"' },
    ],
  },
];

3 · Markdown for Agents

// proxy.ts  (Next 16 = proxy, no middleware)
export default function proxy(req: NextRequest) {
  if (req.headers.get("accept")?.includes("text/markdown")) {
    const url = req.nextUrl.clone();
    url.pathname = `/markdown${url.pathname}`;
    return NextResponse.rewrite(url); // sin query param
  }
}
// app/markdown/[[...path]]/route.ts  — importa de lib/*-data.ts, NUNCA de componentes con SCSS
// params es { path?: string[] } con [[...path]], o el type-check falla en Turbopack

4 · robots.txt que sí permite Content-Signal

// app/robots.txt/route.ts  — route handler, no MetadataRoute.Robots
export async function GET() {
  return new Response(
    `User-agent: GPTBot\nAllow: /\nUser-agent: ClaudeBot\nAllow: /\nContent-Signal: ai-train=no, search=yes, ai-input=yes\nSitemap: https://belmon.tech/sitemap.xml`,
    { headers: { "Content-Type": "text/plain" } }
  );
}
Gotchas Turbopack: A rewrite with ?path= doesn't reach the route handler — use catch-all. Proxy matcher must exclude /_next, /api, /monitoring, /markdown and files with extension. And .well-known goes as route handlers in app/.well-known/..., not in public/ (Next ignores dotfiles).

Validation

curl -H "Accept: text/markdown" https://belmon.tech/readiness/es | head
curl https://belmon.tech/robots.txt
curl -I https://belmon.tech/ | grep -i link
POST https://isitagentready.com/api/scan  {"url":"https://belmon.tech"}
npx ora scan https://belmon.tech  # Deep Scan oficial de AgentReady
Limitations of this recipe

n=1 site (belmon.tech), Next.js 16 + Turbopack, 6 weeks. Doesn't apply as-is to WordPress/CMS nor guarantee citations. Always validate with isitagentready before promising results.


Glossary: llms.txt → · Implementation as service