Why 11ty Is the Right CMS for an AI-Managed Site
An AI agent writing raw HTML for every article is expensive and fragile. Here's why Eleventy fixed that.
The Problem
When I first set up mcinnis.dev, every page was hand-written HTML. That's fine when a human is maintaining a site — you open a file, write your content, push it. But Coral isn't a human. Coral is an AI agent running on Claude, and every token of HTML boilerplate it writes costs money.
A simple blog post in raw HTML looks like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Article Title - mcinnis.dev</title>
<link rel="stylesheet" href="/assets/style.css">
<!-- meta tags, OG tags, schema.org, favicon links... -->
</head>
<body>
<nav><!-- full nav markup --></nav>
<main>
<article>
<h1>Article Title</h1>
<p>Content goes here...</p>
</article>
</main>
<footer><!-- full footer markup --></footer>
</body>
</html>
That's maybe 80 lines of boilerplate wrapping 5 lines of actual content. When an LLM generates that, you're paying for every character of the <nav>, the <footer>, the meta tags, the schema markup. Every article. Every log entry. Every page update.
And if the nav changes? You update every file. If the footer gets a new link? Every file. The agent has to remember the exact structure of the boilerplate and reproduce it perfectly, or things break in subtle ways.
What 11ty Does
Eleventy (11ty) is a static site generator. You write content in Markdown, wrap it in templates, and 11ty compiles everything into static HTML files that a web server can serve directly.
The same blog post becomes:
---
title: "Article Title"
date: 2026-02-21
tags: [blog, topic]
description: "One-sentence description."
layout: post.njk
---
Content goes here.
That's it. The nav, footer, meta tags, OG tags, styles — all handled by the post.njk template once, shared across every article. The agent writes 10 lines instead of 80. The template handles the rest.
Why This Matters for an AI Agent
1. Token efficiency
The most direct benefit. Markdown is dramatically cheaper to generate than full HTML. A 500-word blog post in Markdown is about 600 tokens. The same post wrapped in full HTML boilerplate is 1,500+ tokens. That's a 60% reduction per article, and it compounds — every log entry, every doc page, every content update.
When an agent is writing content autonomously (via cron jobs or on demand), token efficiency directly translates to cost efficiency.
2. Separation of content and presentation
The agent never needs to think about styling, layout, or navigation. It writes content. The templates handle presentation. This means:
- Template changes propagate automatically (new nav link → every page updates on next build)
- The agent can't accidentally break the site layout by forgetting a closing
</div> - Content is portable — if I switch templates tomorrow, every article still works
3. The publishing workflow is dead simple
Coral's entire workflow to publish a blog post:
cat > src/blog/2026-02-21-article-slug.md << 'EOF'
---
title: "Title"
date: 2026-02-21
tags: [blog, topic]
description: "Description."
layout: post.njk
---
Article content.
EOF
npm run build
git add src/blog/
git commit -m "blog: title"
git push
Drop a Markdown file. Build. Commit. Push. The server pulls, rebuilds, and Caddy serves the new static files. No database. No CMS admin panel. No API calls. The "CMS" is the filesystem.
4. Build-time validation
If the Markdown is malformed or a template reference is wrong, npm run build fails and the agent sees the error before pushing. This is a safety net — broken content never reaches the live site. With raw HTML, a typo in a closing tag might not be visible until someone visits the page.
5. Frontmatter is structured data
The YAML frontmatter block at the top of each Markdown file is machine-readable metadata:
---
title: "Article Title"
date: 2026-02-21
tags: [blog, agentic-engineering]
description: "SEO description."
layout: post.njk
---
11ty uses this to automatically generate:
<title>and<meta description>tags- Open Graph tags for social sharing
- Tag-based collection pages
- Sitemap entries
- RSS feed items
The agent sets four fields. The build system generates everything else.
What I Considered Instead
WordPress / Ghost / Strapi
Heavy. Requires a database, a Node/PHP runtime, admin authentication, plugin management. More infrastructure to maintain, more attack surface, more things that can break at 3 AM. For a site managed by an AI agent, simplicity wins.
Next.js / Remix / Astro
Powerful, but over-engineered for this use case. I don't need server-side rendering, API routes, or React components. I need Markdown → HTML. 11ty does exactly that with zero client-side JavaScript by default.
Raw HTML (what we started with)
Works until it doesn't. The moment you want consistent navigation, meta tags, and multiple content types (blog, log, docs), raw HTML becomes a maintenance burden — especially when an AI is doing the maintenance.
Hugo
Solid alternative. Faster builds (Go vs Node). But 11ty's template language (Nunjucks) is more flexible, the plugin ecosystem is richer, and the JavaScript toolchain integrates cleanly with Tailwind CSS (which we use for styling).
The Architecture
src/ ← Agent writes here
├── _includes/
│ ├── base.njk ← HTML shell (nav, footer, meta)
│ └── post.njk ← Blog post template
├── _data/
│ └── site.json ← Site name, URL, description
├── assets/
│ └── style.css ← Tailwind output
├── blog/ ← Markdown → /blog/
├── log/ ← Markdown → /log/
├── docs/ ← Markdown → /docs/
└── index.njk ← Homepage
public/ ← 11ty outputs here → Caddy serves this
The agent only touches src/blog/, src/log/, and src/docs/. Templates, config, and styles are set once and rarely change. The build step compiles everything into public/, which Caddy serves as static files.
Cost Impact
Rough numbers for a content-writing agent session:
| Metric | Raw HTML | 11ty + Markdown |
|---|---|---|
| Tokens per blog post | ~1,500 | ~600 |
| Tokens per log entry | ~800 | ~250 |
| Agent needs to know layout | Yes | No |
| Risk of broken layout | Every edit | Template only |
| Build validation | None | Yes |
| Time to add new content type | Rebuild boilerplate | Add template + folder |
Over dozens of articles and log entries, the token savings alone justify the setup cost. But the real win is reliability — the agent writes Markdown, the build system handles everything else, and broken content never ships.
Tradeoffs
11ty isn't free of costs:
- Node.js dependency on the server — the server needs Node to run
npm run build. Not a problem if you already have Node for other services (we do, for the bridge services). - Build step adds latency — content isn't live until the build runs (~2 seconds). For a personal site, this is invisible.
- Template changes require understanding Nunjucks — if the agent needs to modify the layout, it needs to know Nunjucks syntax. But this is rare — most changes are content, not templates.
- Another abstraction layer — one more thing between the content and the browser. I accept this tradeoff for the benefits above.
Summary
If you're building a site that an AI agent will manage, static site generation is the right architecture. The agent writes cheap, structured Markdown. The build system handles expensive, repetitive HTML. Templates enforce consistency. Frontmatter generates metadata. Build failures catch errors before they go live.
11ty specifically is a good fit because it's minimal, flexible, and stays out of the way. No opinions about client-side frameworks. No mandatory API layer. Just templates and content in, static HTML out.
The simplest tool that solves the problem is usually the right one. For an AI-managed content site, that's a static site generator.
mcinnis.dev runs on 11ty with Nunjucks templates and Tailwind CSS. The content-writer agent publishes by dropping Markdown files and running npm run build. The site currently has 30+ pages, all generated from Markdown source.