Content negotiation allows clients to request different representations of the same resource using the HTTP-standard Accept header, rather than requiring different URLs.
For example, the Vercel documentation uses this technique to respond with markdown when an agent requests docs:
# Responds with HTMLcurl https://vercel.com/docs
# Responds with markdowncurl -H "Accept: text/markdown" https://vercel.com/docsThis guide assumes that your content is authored using markdown in a Next.js app, but can be adapted to your content authoring strategy and framework by converting your content to markdown as it is requested.
First, create a Route Handler that returns markdown responses when it is requested:
import { notFound } from 'next/navigation';import { getMarkdownContent } from '@/lib/content';
export async function GET( _req: Request, { params }: { params: Promise<{ slug?: string[] }> }) { const { slug } = await params; const content = getMarkdownContent(slug?.join('/') ?? 'index');
if (!content) { notFound(); }
return new Response(content, { headers: { 'Content-Type': 'text/markdown', }, });}Add a function to your proxy.ts that handles the Accept header:
import { NextRequest, NextResponse } from 'next/server';
function acceptsMarkdown(request: NextRequest): boolean { const acceptHeader = request.headers.get('accept') || ''; return ( acceptHeader.includes('text/markdown') || acceptHeader.includes('text/x-markdown') )}Then, use the function to rewrite response to the Route Handler you created previously:
export function middleware(request: NextRequest) { const pathname = request.nextUrl.pathname;
if (pathname.startsWith('/docs/') && acceptsMarkdown(request)) { // Rewrite to your markdown route const slug = pathname.replace('/docs/', ''); return NextResponse.rewrite(new URL(`/docs/md/${slug}`)), request.url)); }
return NextResponse.next();}
export const config = { matcher: '/docs/:path*}',};You can now use curl to receive different response types of your content.
# Responds with HTMLcurl https://your-domain.com/docs
# Responds with markdowncurl -H "Accept: text/markdown" https://your-domain.com/docs