惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Help Net Security
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - 【当耐特】
Microsoft Azure Blog
Microsoft Azure Blog
Google DeepMind News
Google DeepMind News
Apple Machine Learning Research
Apple Machine Learning Research
有赞技术团队
有赞技术团队
Y
Y Combinator Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
爱范儿
爱范儿
L
LangChain Blog
IT之家
IT之家
酷 壳 – CoolShell
酷 壳 – CoolShell
MongoDB | Blog
MongoDB | Blog
Hugging Face - Blog
Hugging Face - Blog
G
Google Developers Blog
T
Tailwind CSS Blog
Engineering at Meta
Engineering at Meta
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
宝玉的分享
宝玉的分享
博客园 - 三生石上(FineUI控件)
D
DataBreaches.Net
Recent Announcements
Recent Announcements
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

Vercel News

Vercel Open Source Program: Winter 2026 cohort How Notion Workers run untrusted code at scale with Vercel Sandbox How we run Vercel's CDN in front of Discourse From idea to secure checkout in minutes with Stripe Building Slack agents can be easy Scaling redirects to infinity on Vercel Advancing Python typing Gamma builds design-first agents with Vercel How Avalara turns pipe dreams into patent-pending with v0 Keeping community human while scaling with agents How OpenEvidence built a healthcare AI that physicians actually trust Security boundaries in agentic architectures Skills Night: 69,000+ ways agents are getting smarter Video Generation with AI Gateway We Ralph Wiggumed WebStreams to make them 10x faster How Stably ships AI testing agents in hours, not weeks How we built AEO tracking for coding agents Anyone can build agents, but it takes a platform to run them Introducing Geist Pixel The Vercel AI Accelerator is back with $6m in credits The Vercel OSS Bug Bounty program is now available Introducing the new v0 Run untrusted code with Vercel Sandbox, now generally available How Stripe built a game-changing app in a single flight with v0 How Sensay went from zero to product in six weeks AGENTS.md outperforms skills in our agent evals Agent skills explained: An FAQ Testing if "bash is all you need" AWS databases are now live on the Vercel Marketplace and v0 Use Perplexity Web Search with Vercel AI Gateway
Making agent-friendly pages with content negotiation
Zach CowanSoftware EngineerMitul ShahDesign Engineer · 2026-02-03 · via Vercel News

Agents fetch web pages to answer questions, write code, and complete tasks. When an agent requests a page, it gets everything your browser gets, including navigation menus, stylesheets, JavaScript bundles, tracking scripts, and footer links, when all it needs is the structured text on the page. That extra markup confuses the agent, consumes its context window, and makes every request more expensive.

Link to headingWhat is content negotiation

What agents need is a way to request just the text content of a page, without the browser-specific markup. Content negotiation solves this. It's a standard HTTP mechanism where the client specifies its preferred format via the Accept header, and the server returns the matching representation. Many agents already send Accept: text/markdown when fetching pages, and a server that supports content negotiation can return clean, structured text from the same URL that serves HTML to a browser.

We've updated many of our pages, including our blog and changelog, to support content negotiation. This post walks through how it works, how we implemented it in Next.js, and how to add markdown sitemaps so agents can discover your content.

Link to headingHow agents request markdown

When an agent fetches a page, it includes an Accept header with its format preferences:

Accept: text/markdown, text/html, */*

By listing text/markdown first, the agent signals that markdown is preferred over HTML when available. This works better than hosting separate .md URLs because content negotiation requires no site-specific knowledge. Any agent that sends the right header gets markdown automatically, from any site that supports it.

Try it yourself:

curl https://vercel.com/blog/self-driving-infrastructure -H "accept: text/markdown"

Link to headingImplementing content negotiation in Next.js

The implementation has two parts, a rewrite rule in next.config.ts that detects the header and a route handler that returns markdown.

The rewrite checks the Accept header on every incoming request. When it contains text/markdown, the request gets routed to a dedicated markdown endpoint instead of the default HTML page:

import type { NextConfig } from 'next';

const nextConfig: NextConfig = {

async rewrites() {

function markdownRewrite(prefix) {

return {

source: `${prefix}/:path*`,

has: [

{

type: 'header',

key: 'accept',

value: '(.*)text/markdown(.*)',

},

],

destination: `${prefix}/md/:path*`,

};

}

return {

beforeFiles: [markdownRewrite('/blog'), markdownRewrite('/changelog')],

};

},

};

export default nextConfig;

Rewrite requests with Accept: text/markdown to a dedicated markdown endpoint

The route handler serves the markdown. Our blog content lives in our CMS as rich text, so the route handler converts it to markdown on the fly. If your content is already authored in markdown, you can serve it directly without a conversion step.

app/blog/md/[[...slug]]/route.ts

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',

},

});

}

Convert CMS rich text to markdown and return it with the correct Content-Type

The rich-text-to-markdown conversion preserves the content's structure. Code blocks keep their syntax highlighting markers, headings maintain their hierarchy, and links remain functional. The agent receives the same information as the HTML version, just in a format optimized for token efficiency.

Link to headingPerformance benefits

The HTML version of this page is around 500KB. The markdown version is 3KB, a 99.37% reduction in payload size. For agents operating under token limits, smaller payloads mean they can consume more content per request and spend their budget on actual information instead of markup.

We keep the HTML and markdown versions synchronized using Next.js 16 remote cache and shared slugs, so when content updates in our CMS, both versions refresh simultaneously.

Link to headingMarkdown sitemaps for agent discovery

Content negotiation also works for sitemaps. XML sitemaps are flat lists of URLs with no titles, no hierarchy, and no indication of what each page is about. A markdown sitemap gives agents a structured table of contents with human-readable titles and parent-child relationships, so they can understand what content exists on your site and navigate to what they need.

We serve markdown sitemaps for both our blog and documentation.

Here's the route handler we use to generate a markdown sitemap for blog posts:

app/blog/sitemap.md/route.ts

import { getAllBlogPosts } from '@/app/content';

export const dynamic = 'force-static';

export async function GET() {

const posts = await getAllBlogPosts();

const lines = posts

.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())

.map((post) => `- [${post.title}](/blog/${post.slug}.md)`);

const sitemap = `# Blog sitemap\n\n${lines.join('\n')}`;

return new Response(sitemap, {

headers: { 'Content-Type': 'text/markdown' },

});

}

Generate a markdown sitemap listing all blog posts by date

For documentation or other content with nested sections, a recursive renderer preserves the hierarchy so agents understand which pages are children of which topics:

app/docs/sitemap.md/route.ts

import { createTableOfContents, TocItem } from "@lib/content";

function renderTocItems(items: TocItem[], indent = '') {

let sitemap = '';

for (const item of items) {

sitemap += `${indent}- [${item.title}](/${item.path})\n`;

if (item.children) {

sitemap += renderTocItems(item.children, `${indent} `);

}

}

return sitemap;

}

export async function GET() {

const tableOfContents = createTableOfContents(`content`);

const sitemap = `# Documentation sitemap\n\n${renderTocItems(tableOfContents)}`

return new Response(sitemap, { headers: { 'Content-Type': 'text/markdown' } });

}

Generate a hierarchical markdown sitemap for nested documentation

You can see this in action with the Vercel documentation sitemap.

For agents that don't send the Accept header, a link tag in your HTML <head> provides an alternative discovery path:

<link rel="alternate" type="text/markdown" title="LLM-friendly version" href="/llms.txt" />

Link to headingMaking your site agent-friendly

Content negotiation, markdown sitemaps, and link rel="alternate" tags give agents three ways to find and consume your content efficiently. You can read this page as markdown by sending Accept: text/markdown to any blog or changelog URL on vercel.com, as shown in the curl example above.

For an implementation reference, see how to serve documentation for agents in our knowledge base.