Content negotiation for Next.js
Markdown for agents.
HTML for people.
Same URL.
next-md-negotiate serves text/markdown or text/html based on the Accept header — without splitting your routes.
npm install next-md-negotiateOne request, negotiated response
Same path. Different Accept. Different body.
<!DOCTYPE html>
<html>
<head>…</head>
<body>
<h1>Product 42</h1>
<span>$42.00</span>
</body>
</html># Product 42 **Price:** $42.00 **Category:** Electronics **In Stock:** Yes A premium electronic product with exceptional build quality and innovative features designed for the modern developer workflow.
Try the header
One Accept header is enough to switch formats.
# Product 42 **Price:** $42.00 **Category:** Electronics **In Stock:** Yes A premium electronic product with exceptional build quality and innovative features designed for the modern developer workflow.
How it works
Configure routes, negotiate on Accept, serve both from one path.
Configure
md.config.ts
Map URL patterns to handlers that return markdown. Params are typed from the pattern.
// md.config.ts
export const mdConfig = [
createMdVersion(
'/products/[productId]',
async ({ productId }) => {
return `# ${name}`
}
)
];Negotiate
Accept header
Browsers request HTML. Agents that send Accept: text/markdown get markdown instead.
Browser → Accept: text/html
→ React page
LLM agent → Accept: text/markdown
→ markdown bodyServe
Same URL
No parallel endpoints, no sitemap noise, no duplicate-content risk.
GET /products/42
// Browser
Content-Type: text/html · ~26 KB
// Agent
Content-Type: text/markdown · ~101 BBuilt for production Next.js
Small surface area. Clear defaults.
One URL, two formats
No /api/products/42.md endpoints. The canonical path serves both HTML and markdown.
Type-safe route params
Patterns like /products/[productId] infer TypeScript types for your handlers.
SEO-safe by design
Crawlers see HTML only. No duplicate content, no wasted crawl budget.
Discoverable by agents
Optional LlmHint tells AI clients markdown is available via Accept.
App Router & Pages
Same config and patterns for both Next.js routers.
One-command setup
npx next-md-negotiate init detects your project and wires routing.
Live on this site
This documentation uses next-md-negotiate
Request any page with Accept: text/markdown to get the markdown version.
curl -H "Accept: text/markdown" <this-url>