---
title: "The CMS Isn’t the Problem. The Boundary Is."
id: "503"
type: "post"
slug: "the-cms-isnt-the-problem-the-boundary-is"
published_at: "2026-04-21T05:59:41+00:00"
modified_at: "2026-10-21T06:52:16+00:00"
url: "https://compiledrogue.com/articles/the-cms-isnt-the-problem-the-boundary-is/"
markdown_url: "https://compiledrogue.com/articles/the-cms-isnt-the-problem-the-boundary-is.md"
excerpt: "AI agents are another audience for the web, but that doesn't mean we need to rebuild our content management systems. Here's why I built LLM Markdown to solve the problem at the boundary instead."
taxonomy_category:
  - "Engineering"
taxonomy_post_tag:
  - "AI Agents"
  - "Markdown"
  - "Open Source"
  - "WordPress"
---

##### April 21, 2026 Engineering

## The CMS Isn’t the Problem. The Boundary Is.

An AI agent trying to understand a web page doesn’t need the mega-menu, the newsletter signup, the related-content carousel, or the six calls to action surrounding the article. It needs the information the page was built to communicate.

That sounds obvious. But I can already see the industry preparing to turn a straightforward content-delivery problem into an elaborate new publishing architecture.

I’m not convinced we need one.

**Note****Executive summary:** AI agents are another consumer of web content, not necessarily a reason to rebuild the CMS. For prose-heavy pages, Markdown is a practical alternative to presentation-heavy HTML. I built [LLM Markdown](https://wordpress.org/plugins/llm-markdown/)
 to convert the *server-rendered* WordPress page rather than reconstruct content from database fields, blocks, or plugins. The result is a predictable `.md` URL backed by the existing publishing workflow. It doesn’t promise better AI rankings. It solves a much narrower problem: getting an accurate, structured representation of published content to a client that requests one.

## We’ve seen this machinery before

I’ve been building websites long enough to watch the relationship between content and its consumers change several times.

Search engines learned to crawl pages intended for people. Indexing made it worthwhile to expose site structure and metadata in more deliberate ways. We added sitemaps, canonical URLs, structured data, and an entire industry dedicated to making content legible to search systems. APIs gave applications a more predictable contract than scraping arbitrary website markup.

Those developments weren’t all responses to the same problem, and an API isn’t the same thing as a search index. But there’s a recurring pattern: when a new consumer arrives, the interface between it and the publishing system changes.

Now we have AI agents and language-model workflows. They can consume HTML, JSON, and plenty of other formats, but much of the HTML around an ordinary article exists to support presentation and interaction. For an agent extracting the substance of an article, that extra structure may be unnecessary.

Markdown is useful in that context because it preserves the things prose needs—headings, lists, links, tables, quotations, and code—without requiring the consumer to reconstruct the page from a forest of layout elements.

Not every document is best represented as Markdown. A highly interactive application, a visualization, or an interface whose behavior carries the meaning may need something else. But for a large share of publishing, Markdown is a pretty good fit.

The question, then, is how to produce it without inventing another system to maintain.

## The CMS isn’t the problem

Consider a WordPress site that’s been in production for years.

Some content lives in `post_content`. Some is assembled through Gutenberg blocks. Some comes from Advanced Custom Fields, shortcodes, server-rendered components, custom post types, or theme templates. On a site with any history, it’s probably some combination of all of them.

There are several ways to expose that content to an AI-facing pipeline.

You could read from the database and write a different exporter for every storage convention. You could create new REST responses that enumerate everything an agent might need. You could maintain a parallel Markdown field and make editors responsible for keeping it current. You could even build a second publishing system around the first.

All of those approaches can be legitimate in the right circumstances. But they also create new contracts to maintain. When the template changes, a field moves, or a shortcode begins rendering additional information, will the alternative representation still agree with the public page?

There’s already one place where all of those WordPress conventions converge: **the rendered HTML**.

WordPress, the plugins, and the theme have done the work of assembling the content. Why not use that output as the starting point?

That’s the architectural decision behind [LLM Markdown](https://wordpress.org/plugins/llm-markdown/)
, the free, open-source plugin I built for WordPress.

The plugin doesn’t need to understand how each sentence was authored. It requests the public page, finds the meaningful content, removes what doesn’t belong, and converts the remainder into Markdown. The existing website stays the source of truth.

**Fix the boundary. Leave the CMS alone.**

## This article has two representations

The easiest way to demonstrate the idea is with the article you’re reading.

- [Read this article as HTML](https://compiledrogue.com/articles/the-cms-isnt-the-problem-the-boundary-is/) .
- [Read the same article as Markdown](https://compiledrogue.com/articles/the-cms-isnt-the-problem-the-boundary-is.md) .

Or request the two representations yourself:

HTMLMarkdown

BASH

```
curl -L https://compiledrogue.com/articles/the-cms-isnt-the-problem-the-boundary-is/
```

BASH

```
curl -L https://compiledrogue.com/articles/the-cms-isnt-the-problem-the-boundary-is.md
```

The Markdown URL isn’t a file someone exports and uploads alongside the article. It’s a WordPress route. The document is generated from the existing public page and cached temporarily. Change the article, and the Markdown follows the publishing workflow rather than becoming an unrelated artifact.

That distinction matters. The point isn’t to replace the human-readable site. It’s to let another consumer request a different representation of the same published information.

## How the conversion actually works

The core of the plugin is intentionally unremarkable. WordPress rewrite rules recognize a `.md` URL and resolve it back to a public post, page, or supported custom post type. The renderer uses a safe WordPress HTTP request to retrieve the canonical page’s server-rendered HTML.

From there, the pipeline looks like this:

1. **Resolve and authorize.** Confirm the requested content belongs to an enabled, public post type and is eligible to be served.
2. **Fetch the rendered page.** Request the canonical HTML representation, rather than trying to reconstruct the page from `post_content` alone.
3. **Select the content root.** Match a configured content selector; if necessary, fall back to `main`, `article`, and eventually `body`.
4. **Remove unwanted elements.** Drop scripts, styles, and templates, plus user-configured exclusions such as navigation, forms, or related-content blocks.
5. **Convert to Markdown.** Preserve useful document structure, including headings, lists, links, code, and simple tables. Image output is optional.
6. **Attach metadata and cache.** Prepend YAML front matter and cache the result for subsequent anonymous requests.

The content root and exclusions are configurable because no two themes organize their markup quite the same way. The selector engine supports a practical subset of CSS—elements, IDs, classes, descendants, and direct-child relationships—not the entire CSS selector language.

This is a conscious tradeoff. A little per-site configuration is better than shipping integrations for every page builder, theme, and content framework on the planet.

The metadata matters, too. A Markdown document is more useful to a downstream system when it carries its own identity and provenance. LLM Markdown can include the title, WordPress ID, post type, slug, publication and modification timestamps, canonical and Markdown URLs, excerpt, and public taxonomy terms.

That isn’t an AI-specific trick. It’s simply a useful way to make documents self-describing.

## What rendered HTML doesn’t solve

The approach is deliberately dependent on the server response. If a component exists only after browser-side JavaScript executes, it won’t appear in the fetched HTML. If a theme places important content outside the selected container, you need to adjust your selectors. A badly behaved plugin can even emit output before WordPress has a chance to send the intended response.

Those are real limitations, not reasons to abandon the approach. In practice, they are visible and diagnosable problems at the output boundary. I would rather solve those than maintain separate content models indefinitely.

There is also an important distinction between *serving content* and *granting access*. The `.md` URL must not become a shortcut around visibility settings. Private, unpublished, and password-protected content must remain unavailable, and the plugin supports explicit per-post exclusions and optional noindex checks.

## The HTTP problem is more interesting than the Markdown problem

You can request Markdown through an explicit `.md` URL. Alternatively, HTTP content negotiation allows a client to request a different representation from the normal page URL:

Request Markdown by Accept header

```
curl -i \
  -H 'Accept: text/markdown' \
  https://compiledrogue.com/case-studies/sentinelone/
```

[Cloudflare introduced Markdown for Agents in February 2026](https://developers.cloudflare.com/changelog/post/2026-02-12-markdown-for-agents/)
, using this kind of content negotiation at the network edge. It’s another sign that the format is being taken seriously as an interface for agents.

But there’s a catch: caches.

For content negotiation to behave correctly, every caching layer needs to distinguish the representations. WordPress sites may have a page cache, a hosting cache, a reverse proxy, and a CDN. The response can say `Vary: Accept`, but that header doesn’t guarantee every intermediary will incorporate the header into its cache key.

Get this wrong and an ordinary visitor could receive Markdown where HTML was expected—or an agent could get cached HTML despite explicitly requesting Markdown.

**Warning****Header-based Markdown is disabled by default in LLM Markdown.** Enable it only if you can verify that every relevant cache honors the variation. Explicit `.md` URLs are more predictable because HTML and Markdown have distinct cacheable URLs.

It’s also worth noting that a raw Markdown response doesn’t run browser-side analytics scripts. That’s expected, but operationally relevant for anyone comparing agent traffic with conventional website analytics.

These details are part of the feature, not edge cases to hand-wave away. The hard part of exposing an alternate representation is often everything surrounding the conversion itself.

## This isn’t an AI SEO miracle

I’m wary of the rush to rebrand every technical decision as an AI optimization strategy.

Will publishing Markdown help an agent ingest your content? For an agent that requests or discovers the endpoint, quite possibly. Will it guarantee more citations in AI-generated answers, better rankings, or preferential treatment from a model provider? No. There’s no credible basis for promising any of that.

LLM Markdown advertises eligible Markdown endpoints using HTML alternate links and HTTP `Link` headers. Those make the alternate representation discoverable to clients that understand them. They do not force a crawler to retrieve the document, let alone use it.

That’s fine. Not every useful technology needs to be sold as a growth hack.

I can make a narrower promise and actually test it: request an eligible `.md` URL, and WordPress returns a structured Markdown representation of the published page.

## Make the thing do one thing

This is the second WordPress plugin I’ve released publicly, and it has reinforced my preference for small software that solves a narrow problem.

Too many plugins now manage to do simultaneously too much and too little. You need one feature; you inherit a control panel, an external account, overlapping libraries, and a steady stream of Pro upsells. Sometimes the software starts working against WordPress rather than with it.

I wanted a different experience: install the plugin, choose the content types, adjust a selector if the theme requires it, verify the output, and move on. **Sorted.**

That doesn’t mean shipping an unfinished proof of concept. Real users asked for tables, optional images, and HTTP negotiation. Those requests made the plugin better. Version 1.1 added in-editor Markdown previews, per-post opt-outs, extraction diagnostics, more noindex integrations, and HTTP-header discovery. Each change improved the same core responsibility.

For a full feature walkthrough, setup instructions, and the 1.1 release details, see [LLM Markdown 1.1: What’s New and How It Works](https://compiledrogue.com/articles/llm-markdown-1-1-whats-new-and-how-it-works/)
.

## The boundary keeps changing

I expect the way websites present information to change considerably as more software consumes the web on our behalf. We may eventually think of the website less as a fixed set of page designs and more as curated information that can be rendered differently for different requests.

Maybe that takes a decade. Maybe parts of it happen much sooner. It’s a larger conversation than this plugin.

The practical question today is simpler: when a new consumer needs our existing content in a different form, do we need to rebuild the publishing system—or can we adapt what it already produces?

For a lot of WordPress content, I think the answer is sitting in the rendered page.

[LLM Markdown is available free on WordPress.org](https://wordpress.org/plugins/llm-markdown/)
. If Markdown endpoints are the thing you need, I’d like the plugin to be the thing you install, configure once, and forget about.
