On this page

Wire is a static site generator. It builds HTML. But it also outputs structured content in five machine-readable formats on every build. Override one template file and your site becomes a headless CMS that delivers content to any frontend, any app, any agent.

What Wire already outputs

Every python -m wire.build generates these alongside your HTML:

search_index.json is a JSON array of every page with title, description, url, and body (plain text, HTML stripped). This powers Wire's client-side search, but it is also a content API. Fetch it from any frontend.

llms.txt is a structured text file that tells AI models what your site is and where to find each page. Grouped by section with titles and descriptions. Any agent that reads this URL knows your full content inventory.

feed.xml is an RSS feed with your latest content. Feed readers, newsletter tools like follow.it, and syndication platforms consume this automatically.

sitemap.xml contains every indexable URL with last-modified dates. Search engines and crawlers use this. So can your frontend router.

Raw markdown export contains clean markdown files with frontmatter stripped. Configure which pages to export in wire.yml:

extra:
  wire:
    raw_export:
      - origins/index.md
      - origins/ethiopia/index.md
      - brewing/index.md

Wire writes these as .md files in your site/ directory. Pure content, no metadata, no YAML. Ready for API consumption, content syndication, or feeding into another system.

Strip Wire's chrome with one template

Wire's default raw.html template extends base.html, which includes the header, footer, navigation, and CSS. To make truly headless pages, override it.

Create templates/raw.html in your site directory:

<!DOCTYPE html>
<html lang="{{ lang }}">
<head>
<meta charset="utf-8">
<title>{{ page.title }}</title>
</head>
<body>
{{ page.html | safe }}
</body>
</html>

Any page with layout: raw in its frontmatter now renders as bare HTML. No Wire header, no footer, no CSS, no JavaScript. Just the content.

Wire's template fallback chain checks your templates/ directory first. If it finds raw.html there, it uses yours instead of the default. You can override any template this way: page.html, article.html, landing.html, base.html.

Use cases

Feed a React or Next.js frontend. Wire handles content creation, SEO validation, structured data, and quality checks. Your frontend fetches search_index.json and renders its own UI. Wire is the editorial backend, your framework is the presentation layer.

Syndicate content to partners. The raw markdown export gives partners clean content without your branding. They format it however they want. You keep the canonical version.

Power a mobile app. The search index JSON is a lightweight content API. No server, no database, no authentication. Just a static JSON file behind a CDN.

Build embeddable widgets. Pages with layout: raw and the headless template are self-contained HTML that iframes into any site. Wire's Bean Catcher game was built exactly this way.

Let agents consume your content. llms.txt tells any AI agent what your site offers and where to find it. The agent reads one URL and knows your full inventory. This is what the Bot Protocol uses.

What you keep

Going headless does not mean losing Wire's pipeline. Your content still runs through:

The only difference is the output format. The quality pipeline is the same whether you ship HTML or JSON.

Output JSON instead of HTML

A real headless CMS serves JSON. Wire can do this with one template file and zero code changes.

Create templates/api.json.html in your site directory:

{
  "title": {{ page.title | tojson }},
  "description": {{ page.description | tojson }},
  "url": {{ page.url | tojson }},
  "slug": {{ page.slug | tojson }},
  "word_count": {{ page.word_count }},
  "reading_time": {{ page.reading_time }},
  "created": {{ iso_created | tojson }},
  "html": {{ page.html | tojson }},
  "jsonld": {{ jsonld | tojson }}
}

Then create a page with layout: raw and template: api.json.html in its frontmatter:

---
title: Jamie Tamper
description: API endpoint for Jamie Tamper author data
layout: raw
template: api.json.html
author: jamie-tamper
created: 2026-03-24
---
Extraction obsessive writing about the mechanical details of great coffee.

Wire builds this as a static JSON file. The output at /api/jamie-tamper/index.html:

{
  "title": "Jamie Tamper",
  "description": "API endpoint for Jamie Tamper author data",
  "url": "/api/jamie-tamper/",
  "slug": "jamie-tamper",
  "word_count": 13,
  "reading_time": 1,
  "created": "2026-03-24T09:57:30+00:00",
  "meta": {
    "title": "Jamie Tamper",
    "description": "API endpoint for Jamie Tamper author data",
    "author": "jamie-tamper",
    "layout": "raw",
    "template": "api.json.html"
  },
  "html": "<p>Extraction obsessive and pour-over evangelist...</p>",
  "jsonld": {
    "@context": "https://schema.org",
    "@type": "Article",
    "headline": "Jamie Tamper",
    "author": {
      "@type": "Person",
      "name": "Jamie Tamper",
      "url": "https://beanandbrew.com/authors/jamie-tamper/",
      "jobTitle": "Lead Barista & Coffee Columnist"
    }
  }
}

Valid JSON with every field: title, description, URL, word count, reading time, rendered HTML, and full JSON-LD structured data including resolved author information. A static file behind a CDN. No server, no database, no authentication.

The same trick works for XML. Create a template that outputs XML instead of JSON. Wire does not care what the template produces. It renders Jinja2 and writes the result to disk.

You can create an entire API surface this way. One JSON endpoint per page, or a single index that lists all pages. The content goes through the same 91 quality checks as your HTML pages. The JSON just skips the chrome.

The six outputs

Output Format Updated on build Use case
site/*.html HTML Always Web pages, CDN hosting
site/search_index.json JSON Always Frontend apps, mobile, search
site/llms.txt Text Always AI agents, LLM consumption
site/feed.xml XML Always RSS readers, newsletters
site/*.md (raw export) Markdown When configured Syndication, content APIs
site/api/*/index.html JSON When configured Headless content API

Wire is not a static site generator that can be hacked into a headless CMS. Wire is a content pipeline that happens to output HTML by default. Change the template, keep the pipeline.