On this page

Wire works with any site that has markdown content in a structured directory. The init command generates everything you need, or you can create the config manually.

Three Ways to Use Wire

Standalone homepage. Wire builds and hosts your full site. You get navigation, SEO, search, RSS feed, sitemap, and 91 lint rules on every build. This is the default.

Headless CMS. Wire creates optimized articles. You copy the content to your existing site. Wire handles quality, SEO, and freshness; your site handles design and hosting. The docs/ directory is your content source.

Linter only. You already have a website and just want Wire to check content quality. Two commands, no migration:

cd /path/to/your/articles
python -m wire.chief init    # Creates wire.yml, discovers existing markdown
python -m wire.build         # Runs 91 lint rules, reports every issue

The build output in site/ can be ignored. The value is in the lint report. If you want to fix issues automatically: python -m wire.chief lint-fix (low token usage).

What Wire Generates

Every build produces these automatically:

  • sitemap.xml and robots.txt
  • JSON-LD structured data (Article, FAQ, NewsArticle, author pages)
  • llms.txt for LLM discovery
  • RSS/Atom feed
  • Search page with client-side search index
  • Open Graph and Twitter Card meta tags
  • 91 lint rules checking every page

Hosting is free. Wire generates a static site. Host on GitHub Pages (free, custom domain), Netlify (free tier), Vercel, or any web server. See the GitHub Pages deploy workflow below.

Quick Start with Init

cd /path/to/my-site
python -m wire.chief init

Wire generates wire.yml, _styleguide.md, templates, and a .env template. If mkdocs.yml exists, Wire migrates settings from it: site name, URL, docs directory, theme colors, and extra.wire configuration.

Wire requires wire.yml for building (python -m wire.build). The editorial pipeline (chief, content, news) also reads mkdocs.yml as a legacy fallback during migration, but logs a warning nudging you to create wire.yml.

Manual Setup

Create a wire.yml config file and a docs/ directory with markdown content. Templates and CSS are optional. Wire ships sensible defaults.

# wire.yml
site_name: My Agency Blog
site_url: https://blog.agency.com
description: B2B marketing insights and case studies.
docs_dir: docs
templates_dir: templates
output_dir: site

Define your site structure in nav:. Wire does not auto-discover topics. Navigation is a strategic decision. Every section and page must be explicitly declared.

Content Structure

Wire expects this file layout:

docs/
  index.md                          # Homepage
  insights/                          # Topic: insights
    index.md                        # Topic index page
    content-strategy/
      index.md                      # Content page
    seo-fundamentals/
      index.md                      # Content page
  case-studies/                      # Topic: case-studies
    index.md
    client-a/
      index.md

Every index.md needs YAML frontmatter with at least title. Wire uses the directory name as the slug and the parent directory as the topic.

Customizing Prompts

Wire's built-in prompts work for most sites. To customize how Claude writes for a specific topic, create a prompt override.

docs/
  _styleguide.md                    # Site-wide editorial rules
  insights/
    _create.md                      # Custom create prompt for insights topic
    _update.md                      # Custom update prompt for insights topic

Place _styleguide.md in your docs root for site-wide rules. Place _{action}.md in any topic directory for topic-specific instructions. Wire prepends the styleguide to every prompt automatically.

See the prompt engineering guide for details on writing effective prompts.

Wire Configuration

Optional settings go under extra.wire in your wire.yml:

extra:
  wire:
    refresh_days:
      insights: 30
      case-studies: 90
    default_refresh_days: 60
    reword_tiers:
      full: 20
      light: 30
    max_articles: 20
    rate_limit_delay: 1
    min_opportunity_score: 15

See the configuration reference for all available options.

Templates and Assets

Wire ships default templates and CSS/JS. You only override what you want to change.

How Overrides Work

Wire checks your templates/ directory first, then falls back to wire/templates/. Same file name = your version wins. This is how Wire's own documentation site works. It overrides only the header (for the "Wire" logo) and keeps everything else default:

newsroom/
  templates/
    partials/
      header.html          # Custom: hardcoded "Wire" logo
  wire/
    templates/
      base.html            # Default: used as-is
      page.html            # Default: used as-is
      landing.html         # Default: used as-is
      partials/
        header.html        # Ignored: overridden above
        nav.html           # Default: used as-is
        footer.html        # Default: used as-is

Assets work the opposite direction for safety. Wire copies its defaults first (wire/assets/), then overlays your files (docs/assets/) on top. Your CSS/JS files overwrite the defaults with the same name.

wire/assets/               # Copied first (defaults)
  css/wire.css
  js/scroll-title.js
  js/toc-spy.js
  js/back-to-top.js
  ...

docs/assets/               # Overlaid second (your overrides)
  css/wire.css             # Replaces default CSS
  images/logo.png          # Added alongside defaults

Default Templates

Template Purpose
base.html HTML skeleton: head, body, header, nav, main, footer
page.html Article layout: TOC, reading progress, content
landing.html Full customer freedom, splits at <hr> into section bands, no width constraints
raw.html Minimal wrapper, no nav or chrome
partials/header.html Site header with logo and navigation
partials/nav.html Sidebar navigation with active states
partials/footer.html Site footer

Templates receive a page object (title, description, html, url, reading_time, word_count, meta), a nav list (sections with children), and a site dict (name, url, description).

reading_time is calculated at 220 words per minute (minimum 1 minute). It appears in JSON-LD structured data as wordCount and timeRequired (ISO 8601 duration, e.g. PT5M for a 5-minute read).

Default JS (zero config)

These features work automatically on every page, no configuration needed:

File What it does
scroll-title.js Replaces site name with page title when scrolling past header
toc-spy.js Highlights current section in table of contents
back-to-top.js Fixed button appears after 400px scroll
reading-progress.js Thin bar at top tracking scroll position
code-copy.js "Copy" button on code blocks, appears on hover
discovery.js Interactive guided reading (requires steps.md)
yt-embed.js Lazy-loads YouTube embeds from thumbnail
tabs.js Tab component for content switching
forms.js Form validation and submission

Building

cd /path/to/my-site
python -m wire.build --site .

The output goes to site/ by default. Deploy it to any static hosting: Netlify, Vercel, S3, SiteGround, or a simple web server.

GitHub Pages

Create .github/workflows/deploy.yml:

name: Deploy to GitHub Pages

on:
  push:
    branches: [master]

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: pages
  cancel-in-progress: false

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install Wire
        run: |
          curl -L -o /tmp/wire-0.0.0-py3-none-any.whl \
            https://wire.wise-relations.com/dist/wire-0.0.0-py3-none-any.whl
          pip install /tmp/wire-0.0.0-py3-none-any.whl

      - name: Build site
        run: python -m wire.build

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: site

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

Enable GitHub Pages in your repository settings (Settings > Pages > Source: GitHub Actions). Pushes to master trigger a build and deploy automatically.

If your repository URL is https://github.com/you/my-site, the site deploys to https://you.github.io/my-site/. Set site_url in wire.yml to match. Wire derives the subdirectory path from the URL automatically.

Connecting GSC

If your site is verified in Google Search Console, add OAuth credentials to .env and run python -m wire.chief data. This enables all SEO automation features: keyword analysis, cannibalization detection, opportunity scoring, and content gap detection.

GSC integration is optional. Wire's content pipeline and news intelligence work without it.

What Wire Does on Day One

A new site connected to Wire immediately benefits from three automated capabilities that would take a human team weeks to replicate.

Structural audit. Wire scans every page for the issues that Screaming Frog's 2024 data shows average 3.2 per 100 pages: duplicate titles, missing H1 tags, broken internal links, heading hierarchy violations, thin content, missing meta descriptions. The audit runs in seconds and costs nothing.

Cannibalization detection. If you connect GSC, Wire runs a SQL self-join across all keyword-page combinations to find pages competing for the same search terms. First Page Digital uses 30% shared impressions as the cannibalization threshold. Wire uses a dual signal (overlap ratio + traffic skew) that is more precise. It distinguishes between a dominant page absorbing a weak one (merge) and two pages confusing Google equally (differentiate both).

Content gap identification. Wire finds keywords where search demand exists (impressions) but no page on your site ranks well (best position above 20). These represent opportunities for new content. On a typical 100-page B2B site, Wire identifies 5-15 content gap clusters on the first audit.

The first week with Wire typically follows this pattern:

  1. Day 1: Connect the site, run data and audit. Review findings.
  2. Day 2: Run deduplicate to resolve cannibalization. Review merges with --dry-run first.
  3. Day 3: Run sanitize to fix broken internal links (zero cost, no API calls).
  4. Day 4: Run enrich on the highest-opportunity pages. Minimal token usage.
  5. Day 5: Run build and deploy.

By end of week one, you have resolved keyword cannibalization, fixed structural issues, and enriched your best pages with targeted keyword content. Total token usage for a 100-page site is minimal, covered by your AI subscription. See pricing.

Sites Wire Works Best With

Wire is built for content-heavy sites where search traffic matters. The sweet spot is 50-2,000 pages of informational or commercial content: product pages, service descriptions, guides, comparisons, industry analysis.

Wire is not the right tool for single-page applications, e-commerce product catalogs with thousands of identical templates, or sites where content is generated from a database (job boards, real estate listings). These sites need different architectures.

The sites that get the most value from Wire share three characteristics: they have enough pages that manual SEO is impractical, they compete for search traffic in a defined niche, and they have (or can get) Google Search Console access for their domain.

Build Output Files

Wire auto-generates these files during every build:

File Purpose
sitemap.xml Page index for search engines
robots.txt Crawler access rules with Sitemap directive
feed.xml RSS feed, sorted by date descending, 20 most recently modified pages
feed_rss_created.xml Legacy alias, same content as feed.xml
search_index.json Client-side search data (full page body + all frontmatter metadata)
llms.txt and llms-full.txt AI-readable site summaries
.htaccess Apache redirect rules (when deploy.target: apache)
404.html Custom 404 error page
CNAME GitHub Pages custom domain (when configured)
bot/ Agent-facing site context (opt-in via extra.wire.bot_dir: true)
.wire/build-errors.txt All gate + lint errors persisted for reference after build

JSON-LD Timestamps

Wire maps created to datePublished and date to dateModified in JSON-LD and OG meta tags (article:published_time/article:modified_time). Date-only values (2026-02-10) are auto-converted to full ISO 8601 timestamps. Google requires full timestamps to display dates in SERP snippets.

  • Today's date: uses the real current time (never claims a future time on today's date)
  • Past dates: derives a deterministic time from the date string (consistent across pages and builds)
  • Safe for multiple builds per day. Same past date always produces same timestamp.

Author JSON-LD includes jobTitle from the author page's role: frontmatter for E-E-A-T.

See the Guides overview for all Wire documentation.