Back in January I wrote Serving Markdown for AI Agents: for every page on this blog, there’s also a .md version at the same URL, discoverable via a <link rel="alternate" type="text/markdown"> tag, so AI agents can fetch clean Markdown instead of parsing HTML. It also made me $360, via referral conversions an AI agent apparently generated after reading the clean Markdown version of a post.

That worked, but it lived in this repo as a one-off script, _scripts/render_markdown.rb, wired into the GitHub Actions deploy workflow (needed since GitHub Pages’ native build only allows a small allowlist of plugins, which jekyll-md isn’t on), with the <link> tags added by hand via Liquid and a markdown_url front matter field on every page.
I’ve since extracted all of it into jekyll-md, a proper Jekyll plugin. It does the same thing - converts each page’s fully rendered HTML output to Markdown and injects the discovery <link> tag - but as a Jekyll::Generator and Jekyll::Hooks, with no external script or per-page front matter required.
What Changed
Add the gem and enable the plugin:
# Gemfile
gem 'jekyll-md'
# _config.yml
plugins:
- jekyll-md
If you don’t configure anything else, jekyll-md looks for <main> or [role="main"] before falling back to the whole <body>, since that’s the closest thing HTML has to a content/chrome convention. You can also configure a CSS selector to convert from, e.g. md: selector: "#markdown-content", and other options - see the README for the full list.
What About llms.txt?
There’s a related convention, llms.txt, a single root-level file that’s supposed to give an AI agent a curated map of a site. I considered adding llms.txt generation to jekyll-md, then didn’t. The spec is explicit that the file should “stay small enough to fit in context” and contrasts itself with sitemap.xml, which it calls out for being too large and unfiltered to be useful. A plugin walking every page and dumping it into llms.txt - which is what some similar plugins do by default - just recreates the sitemap problem in Markdown instead of solving it. This blog alone has almost 600 posts; nobody wants all of them in one file.
Instead, I wrote llms.txt by hand as a plain Jekyll page with Liquid front matter, listing a handful of pinned posts, the 10 most recent ones, and a few key pages, reusing this blog’s existing pinned: true front matter flag rather than inventing a new mechanism. You can see the result at code.dblock.org/llms.txt and the template that generates it.
