Auto-Serve Markdown
Learn how to automatically serve markdown to AI agents using content negotiation.
Overview
When autoServeMarkdown is enabled, LLMify uses content negotiation to serve markdown instead of HTML. If a request contains an Accept: text/markdown header, the same URL that normally returns HTML will return clean markdown instead.
This approach is inspired by Cloudflare's Markdown for Agents. It allows AI agents to request your existing page URLs and receive structured markdown without needing separate /raw/<slug>.md endpoints.
This works well in combination with the isRealUrlLlm setting. When both are enabled, llms.txt will point to your real page URLs, and AI agents can request those URLs with the Accept: text/markdown header to get the markdown version.
Setup
Enable the setting in your config file or in the Control Panel under Settings → LLMify.
<?php
return [
'autoServeMarkdown' => true,
'isRealUrlLlm' => true, // recommended with auto-serve
];
Make sure your templates use the {% llmify %} tags, and that markdown has been generated for your entries. You can trigger generation via the LLMify Utility or Console Commands.
How It Works
When a request with Accept: text/markdown hits a page:
- LLMify checks if cached markdown exists for the requested entry.
- If no cached version exists, it generates the markdown on-the-fly from the template output.
- The response is returned with
Content-Type: text/markdownand aVary: Acceptheader.
The Vary: Accept header tells browsers and CDNs that the response differs based on the Accept header, so they cache the HTML and markdown versions separately.
Testing
You can test auto-serve with curl:
# Request markdown
curl -H "Accept: text/markdown" https://your-site.com/about
# Compare with normal HTML
curl https://your-site.com/about
Blitz Integration
LLMify works with Blitz out of the box when using the default Blitz caching strategy. LLMify automatically tells Blitz to skip its cache for Accept: text/markdown requests, so the request is passed through to PHP where LLMify can handle it.
Blitz with Server Rewrites
If you use Blitz with Nginx server rewrites, Nginx serves cached pages directly from the file system without ever hitting PHP. In this case, LLMify cannot intercept the request.
To fix this, add a condition to your Nginx config that skips the Blitz cache when the Accept header contains text/markdown:
set $cache_path false;
if ($request_method = GET) {
set $cache_path /cache/blitz/$host/$uri/index.html;
}
if ($args ~ "token=") {
set $cache_path false;
}
# Skip Blitz cache for text/markdown requests (LLMify auto-serve)
if ($http_accept ~ "text/markdown") {
set $cache_path false;
}
location / {
try_files $cache_path $uri $uri/ /index.php?$query_string;
}