October 17, 2026

How to Add Markdown Alternates to a Website

Request flow from an HTML page to its Markdown alternate, showing the Accept header check, rel=alternate link, and canonical back to HTML
Photo: Magic Teams AI / generated in the build

To add a Markdown alternate to a website, publish a clean Markdown version of a page at its own URL (for example /pricing.md), point to it from the HTML page with <link rel="alternate" type="text/markdown">, and keep the HTML page as the complete, canonical version. If you also answer Accept: text/markdown requests on the original URL, send Vary: Accept so caches don’t mix the two up. Then check your logs to see whether anything actually asks for it.

That’s the whole job. The harder part is deciding which pages deserve it and keeping the two versions saying the same thing.

Say you run a 20-person agency. Someone on the team read that AI agents “prefer Markdown” and wants a .md copy of every page by Friday. This post covers what’s worth doing, where to stop, and what it looks like when you build it.

What is a Markdown alternate, exactly?

It’s a second representation of the same page, served as plain Markdown instead of HTML. Same facts, same headings, same links. No menus, scripts, cookie banners, or layout markup.

The media type is text/markdown, registered in RFC 7763 in 2016. That RFC makes the charset parameter required, so send Content-Type: text/markdown; charset=utf-8.

The word “alternate” matters. Think of it like an RSS feed or a PDF of a report: the same content in another format. A page written only for bots would be something else entirely, and keeping that boundary is what keeps you on the right side of search policy.

Does Google need a Markdown version of your pages?

No. Google’s AI optimization guide says you don’t need to create “new machine readable files, AI text files, markup, or Markdown to appear in Google Search,” because Google Search doesn’t use them. The same guide says optimizing for generative AI search “is optimizing for the search experience, and thus still SEO.”

John Mueller has been blunter. Asked about Markdown pages for LLM crawlers, he pointed out that LLMs have read normal web pages since the beginning, and asked, “Why would they want to see a page that no user sees?”

So the honest case for a Markdown alternate is convenience for the AI agents and tools that fetch pages directly, mainly coding assistants and research agents. For them, a clean text copy is smaller and easier to parse.

Vercel reported that one of its blog pages weighed about 500KB as HTML and 3KB as Markdown. That’s a real saving for an agent working inside a context window. It says nothing about whether a search engine will rank or cite you.

Who actually asks for Markdown?

Some agents do. Most don’t, yet.

In a February 2026 test of seven coding agents, Checkly found that three (Claude Code, Cursor, and OpenCode) put text/markdown in their Accept header. The other four sent browser-style headers or */*, so they’d get your HTML regardless.

That’s why the discoverable link matters. Content negotiation only helps clients that ask. A <link rel="alternate"> in the HTML helps any client that reads the page head.

Which pages should get a Markdown alternate?

Start with pages an agent might be sent to do a job with. Skip pages that only make sense visually.

Page type Worth a Markdown alternate? Why
Docs, API references, integration guides Yes, first Agents read these to write code or answer setup questions
Pricing, service scope, policies Usually Facts an agent quotes back need to be exact
Long-form answer posts Optional Helpful if your HTML is heavy; low priority if it’s already clean
Homepage Maybe, as a summary Point to an “about” style overview, and say what it is
Landing pages, case-study layouts, tools No The meaning lives in the design or the interaction
Gated or personalized pages No Never expose in Markdown what users can’t see in HTML

If your HTML is already lean and server-rendered, the gain is small. Fix crawlable HTML first. A Markdown file can’t rescue a page whose real content only appears after JavaScript runs.

Here’s the decision in one view.

How do you add a Markdown alternate, step by step?

We use a four-part check we call Mirror, Link, Point, Check. It came from building and then auditing the Markdown endpoint on this blog, described below. Each step covers a gap we either found in our own setup or saw handled in public examples like Cloudflare’s and Vercel’s.

1. Mirror: build it from the same source

Generate the Markdown from the same content file or CMS entry that builds the HTML. Don’t hand-write a second copy. Hand-written copies drift, and drift is how you end up telling agents a price you changed three months ago.

Keep the H1, headings, body text, tables, and links. Use absolute URLs, since the Markdown may be read out of context. Strip menus, footers, and scripts.

Add this to the HTML <head>:

<link rel="alternate" type="text/markdown" href="https://example.com/services/seo-audit.md">

You can send the same hint as an HTTP header, which helps clients that only read headers:

Link: <https://example.com/services/seo-audit.md>; rel="alternate"; type="text/markdown"

3. Point: keep HTML canonical

On the Markdown response, add a canonical Link header pointing back to the HTML page. Google supports rel="canonical" in HTTP headers for non-HTML documents, using full URLs.

Content-Type: text/markdown; charset=utf-8
Link: <https://example.com/services/seo-audit/>; rel="canonical"

If you also serve Markdown on the original URL when a client sends Accept: text/markdown, add Vary: Accept to both versions. Without it, a CDN or browser cache can store one version and hand it to the wrong client. Cloudflare’s Markdown for Agents feature adds Accept to Vary for exactly this reason, so caches keep separate variants.

4. Check: test parity and watch logs

Before you ship, compare the two versions. Same H1, same prices, same dates, same links. Then log requests to .md URLs and Accept: text/markdown hits for a month, and look at which user agents show up.

If nothing useful requests them, that’s worth knowing too. You can stop at the pages you’ve done.

What does this look like on a real site?

Here’s our own setup on blog.magicteams.ai, as it stands while I (Satya Phanindra Reddy, founder of Magic Teams AI) write this. It’s small on purpose.

The homepage sends a Link header announcing /aios.md as a text/markdown alternate and /llms.txt as a describedby resource. A Cloudflare Worker also checks the Accept header: if a client asks for text/markdown on /, it gets the Markdown file instead of the HTML. Every other URL goes straight to static assets.

Personal insight

When I checked our homepage with curl for this post, three things were missing. The responses don’t send Vary: Accept, even though the same URL can return HTML or Markdown. The Markdown response says text/markdown with no charset and no canonical pointing back to the HTML. And /aios.md is a hand-written site summary, not a mirror of the homepage, so “alternate” oversells it a little. Those are exactly the gaps Mirror and Point are meant to catch.

That audit needed nothing more than two commands you can run on your own site today:

curl -sI https://yoursite.com/
curl -s -D - -o /dev/null -H "Accept: text/markdown" https://yoursite.com/

Look for Content-Type, Vary, and Link in each response.

Worked example: one agency service page

This one is hypothetical. It shows the full pattern for a single page, not results from a client install.

Imagine an agency with a service page at /services/seo-audit/. It lists scope, turnaround, and a starting price. Some prospects paste that URL into an AI assistant and ask, “What does this include and what does it cost?”

The request flow looks like this.

The Markdown file at /services/seo-audit.md is built from the same CMS entry:

# SEO Audit for B2B Service Firms

> Canonical page: https://example.com/services/seo-audit/

Scope: technical crawl, content gap review, internal link map.
Turnaround: 10 business days.
Starting price: see https://example.com/pricing/

## What's not included
- Ongoing content production
- Paid search management

Notice the price line. If pricing changes often, link to the pricing page rather than copying a number into two places. That’s a Mirror decision.

A minimal Cloudflare Worker version of the negotiation looks like this:

export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    const wantsMd = /text\/markdown/i.test(request.headers.get('Accept') ?? '');
    const isPage = url.pathname === '/services/seo-audit/';

    const res = await env.ASSETS.fetch(
      isPage && wantsMd ? new Request(new URL('/services/seo-audit.md', url), request) : request
    );
    if (!isPage) return res;

    const headers = new Headers(res.headers);
    headers.append('Vary', 'Accept');
    if (wantsMd) {
      headers.set('Content-Type', 'text/markdown; charset=utf-8');
      headers.set('Link', '<https://example.com/services/seo-audit/>; rel="canonical"');
    } else {
      headers.set('Link', '<https://example.com/services/seo-audit.md>; rel="alternate"; type="text/markdown"');
    }
    return new Response(res.body, { status: res.status, headers });
  },
};

On Next.js, Vercel describes doing the same thing with a rewrite rule that checks the Accept header. On Cloudflare Pro, Business, or Enterprise plans, Markdown for Agents can convert HTML at the edge without code.

One caveat on that last option. Cloudflare’s docs say that if your origin doesn’t set a content-signal header, the converted response defaults to ai-train=yes, search=yes, ai-input=yes. If you have a position on AI training use, set the header yourself. For client data or licensed content, talk to your lawyer before publishing any machine-readable copy.

Content negotiation or separate .md URLs?

Do both if you can. If you can only do one, choose the separate URL.

Separate .md URL Content negotiation on the same URL
Works for agents that don’t send Accept: text/markdown Yes, via the link No
Caching risk Low Needs Vary: Accept
Easy to test Open the URL Needs curl with a header
Canonical handling Link header to HTML Same URL, so mostly automatic

A separate URL plus a <link rel="alternate"> works for every client that reads your HTML head. Negotiation is a nice extra for the agents that ask.

What should you never do with a Markdown alternate?

Don’t put anything in the Markdown that isn’t on the HTML page. No extra claims, no keyword lists, no “notes for AI.” Google defines cloaking as presenting different content to users and search engines with the intent to manipulate rankings and mislead users. Keep both versions identical in substance and you never get near that line.

Don’t block the HTML page and leave only Markdown open. Don’t let the Markdown go stale. And don’t promise anyone this will get you cited in AI answers, because nobody can show that it does.

Here’s the pre-ship checklist.

FAQ

Will a Markdown alternate hurt my SEO?

Not if it mirrors the HTML and points canonical back to it. Google’s guide says Google Search doesn’t use these files, so it won’t help either. The risk comes from using the Markdown to say things the page doesn’t.

Is this the same as llms.txt?

No. llms.txt is one site-level index of important links. A Markdown alternate is a per-page copy. They work well together, and we cover the index side in how to use llms.txt without overpromising.

Should I noindex the Markdown files?

A canonical header to the HTML is usually enough, and it keeps the files fetchable. Some teams use X-Robots-Tag: noindex instead. Pick one approach rather than sending mixed signals. Just don’t block the files in robots.txt if you want agents to reach them.

How many pages should I start with?

Five to ten. Pick your docs, pricing, and core service pages, ship them, and read a month of logs before doing more.

Where this fits in a bigger AI search plan

A Markdown alternate is a small technical courtesy. The work that moves things sits upstream: clear answers, real evidence, and pages that are easy to crawl. That’s what answer engine optimization for B2B is about.

If you want this to run without someone remembering to regenerate files, it belongs inside a publishing workflow, like the one in how to build an AI search content system. And if you’re deciding whether any of it is worth the hours, measure it the way you’d measure any automation, using how to measure ROI on AI automation.

If you’d like your site, content, and review steps connected so changes like this happen once and stay correct, that’s the kind of human-in-the-loop system we set up at Magic Teams. A fit call is a quick way to see whether it makes sense for you.