Skip to content

Next.js / Nuxt / SSG

For frameworks without WordPress’s plugin model — Next.js, Nuxt, SvelteKit, Astro, Eleventy, anywhere static export or SSR happens at the framework layer.

Middleware reads the Accept header on every HTML response. When text/markdown is preferred, return the route’s markdown variant with Content-Type: text/markdown; charset=utf-8, Vary: accept, and x-markdown-tokens: N.

Generate .md for every route at build time. Serve it as /{slug}/index.md so agents that do not negotiate can guess the URL — this is requirement 06, mandatory because of the seven-coding-agents test (only Claude Code, OpenCode, and Cursor send the Accept header).

Static-export pipelines need to preserve <script type="application/ld+json"> blocks through markdown conversion. Cloudflare’s converter does this automatically; custom pipelines need the equivalent.

The route.ts handler with headers().get('accept') is the cleanest negotiation point:

export async function GET(req: Request) {
const accept = req.headers.get('accept') ?? '';
if (accept.includes('text/markdown')) {
return new Response(await renderMarkdown(), {
headers: {
'Content-Type': 'text/markdown; charset=utf-8',
'Vary': 'accept',
'x-markdown-tokens': String(tokenCount),
},
});
}
return new Response(await renderHTML(), {
headers: { 'Content-Type': 'text/html; charset=utf-8', 'Vary': 'accept' },
});
}

Keep Vary: accept in every response or the CDN will poison the cache.

llms.txt, llms-full.txt per section, and /.well-known/* files (agent-statement, api-catalog, oauth metadata, mcp/server-card, agent-skills/index) all ship as static assets in public/. No middleware required for static paths.