On this page

Wire reads configuration from three sources: wire.yml in your site directory, environment variables in .env, and prompt files in your docs directory. This reference covers every option.

wire.yml: Site Configuration

# Required
site_name: My Site
site_url: https://example.com
lang: en                       # Language code for <html lang="">
logo: assets/logo.svg          # Path to logo image (relative to docs_dir)
favicon: assets/favicon.svg    # Path to favicon (relative to docs_dir)
docs_dir: docs

# Recommended
description: What your site is about.
templates_dir: templates
output_dir: site

# Navigation (required - Wire does not guess your site structure)
nav:
  - index.md
  - Insights:
    - Content Strategy: insights/content-strategy/index.md
    - SEO Fundamentals: insights/seo-fundamentals/index.md

# Build exclusions (optional)
exclude:
  - ".*/_.*\\.md$"
  - ".*/drafts/.*"

# Site-wide custom CSS (optional)
extra_css:
  - assets/css/brand.css

# Raw HTML injected into <head> on every page (optional)
extra_head:
  - '<script>/* tracking */</script>'

# GSC coverage exclusions (optional)
# Paths handled by non-Wire apps on the same domain.
# Wire's GSC build guard skips URLs matching these prefixes.
exclude_gsc_data_for_path:
  - /tools/

# Wire-specific settings (all optional)
extra:
  wire:
    refresh_days:
      products: 21
      services: 60
      guides: 120
      comparisons: 0
    default_refresh_days: 21

    reword_tiers:
      full: 20
      light: 30

    max_articles: 20
    rate_limit_delay: 1
    min_opportunity_score: 15
    newsweek_batch_chars: 150000

Header: Two-Row Navigation

Wire uses an IBM Think-style two-row header. Row 1 (offerings) scrolls away; Row 2 (content nav) stays sticky. Sites without header.offerings render a single sticky row.

Required: Sites with topics must configure header.offerings and header.cta. Set each to false to explicitly disable. The build refuses without them: Wire does not guess your navigation.

header:
  offerings: about          # Topic name - resolves child pages for Row 1
  links:                    # Custom links in Row 1 (right side, next to search)
    - Support: https://support.example.com    # External: opens in new tab
    - Pricing: /pricing/                       # Internal: same tab
  cta:                      # Button in the sticky nav bar (Row 2, right side)
    label: Get Started
    url: /guides/getting-started/

offerings

header.offerings accepts a topic name (string). Wire resolves child pages from that topic into Row 1 links and removes the topic from Row 2. The build fails if the topic doesn't exist in nav.

Layout requirement: Every offerings child page must have layout: landing in its frontmatter. These are marketing pages, not articles. The build refuses without it.

For manual control, pass a list instead:

header:
  offerings:
    - Products: /products/
    - Services: /services/

header.links adds custom text links to Row 1. Each entry is a Label: URL pair. External URLs (starting with http) automatically open in a new tab. Use this for support portals, login pages, parent company links, or anything that belongs in the business nav.

cta

The CTA button appears at the right end of the sticky Row 2 nav. It should link to your highest-priority conversion page (getting started, contact, pricing).

Layout requirement: The CTA target page must have layout: landing in its frontmatter. The build refuses without it.

Wire validates your nav configuration at build time. These checks prevent common mistakes:

Alphabetical order. If you have 3 or more nav sections in exact alphabetical order (e.g. "Authors, Content, Guides, SEO, Services"), the build refuses. Alphabetical order means you dumped topics without thinking about priority. Reorder by importance: put your highest-value topic first.

Duplicate URLs. The same URL cannot appear in both offerings (Row 1) and content nav (Row 2). If you want a topic in the offerings bar, it automatically leaves the content nav. Do not add it back manually. If you need a page in both rows, create a separate landing page for the offering.

CTA not in nav. If you manually set header.cta, the CTA URL must not also appear as a content nav section. The CTA button is its own navigation element. Remove the page from nav sections, or point the CTA at a different page.

No topic reuse. Do not point an offerings link at a topic index page that is also in your content nav. Create a dedicated landing page for each offering instead.

Wire auto-generates a search page at /search/ and shows a search icon in the header. The search uses search_index.json (also auto-generated) for client-side full-text search across all pages.

To disable search:

search: false

Every article page renders a sticky card in the right column. This is required. The build refuses without it.

extra:
  wire:
    sidebar_cta:
      label: Agency               # Badge text (optional)
      title: "Let us run it"      # Card title (required)
      description: "Full-service content operations."  # (optional)
      link: https://example.com   # CTA link (required)
      link_text: "Talk to us"     # Link label (required)

Real-world example (wise-relations.com, promotes the Wire pipeline itself):

extra:
  wire:
    sidebar_cta:
      label: "Behind the scenes"
      title: "Watch me Wire"
      description: "This website is managed via Wire using a Telegram Bot. Automated content, zero manual editing."
      link: "https://wire.wise-relations.com"
      link_text: "Watch us Wire"

Article Bottom CTA

Every article page renders a full-width CTA banner between the content body and related articles. This is required. The build refuses without it.

extra:
  wire:
    article_cta:
      title: "Ready to get started?"      # Heading (required)
      description: "Book a free call."     # Paragraph (required)
      link: /contact/                      # Button URL (required)
      link_text: "Get in touch"            # Button label (required)

This is separate from sidebar_cta: use different copy. The sidebar card is compact (right column), the bottom CTA is a full-width conversion banner designed to catch readers who scroll to the end.

Multi-Language CTA

On multi-language sites, nest CTA config by language code. Wire detects the per-language format automatically when any top-level key matches a configured language code.

extra:
  wire:
    sidebar_cta:
      en:
        title: "Your CTA"
        description: "Description"
        link: /en/your-page/
        link_text: "Learn more"
      de:
        title: "Ihr CTA"
        description: "Beschreibung"
        link: /de/ihre-seite/
        link_text: "Mehr erfahren"
    article_cta:
      en:
        title: "Ready?"
        description: "Book a consultation."
        link: /en/contact/
        link_text: "Get in touch"
      de:
        title: "Bereit?"
        description: "Beratung buchen."
        link: /de/kontakt/
        link_text: "Kontakt"

Each configured language must have a complete entry. Wire refuses to build with missing language keys.

footer:
  tagline: "Your site description."
  links:
    Product:
      - Features: /features/
      - Pricing: /pricing/
    Resources:
      - Docs: /docs/
      - Blog: /blog/
  copyright: "© 2026 Your Company"
  legal:
    - Privacy: /privacy/
    - Terms: /terms/

Logo and Favicon

Required. Wire refuses to build without both logo and favicon. Set a file path or explicitly opt out with false.

# Image logo in header
logo: assets/logo.svg

# Text-only mode (shows site_name)
logo: false

# Favicon in browser tab
favicon: assets/favicon.svg

# No favicon
favicon: false

File paths are relative to docs_dir. Wire validates the file exists at build time: a missing file is a build error, not a silent omission.

The logo appears in the header navigation (Row 1 offerings bar and Row 2 sticky bar). Recommended format: SVG for sharpness at all sizes. The image is rendered at 28px height with auto width.

The favicon is emitted with an absolute URL (href="/assets/favicon.svg") on every page. The same string appears sitewide so Google's favicon extractor keys one entity per site instead of one per depth. When the favicon is SVG, PNG, ICO, JPG, WebP, or GIF, Wire also emits the type attribute (e.g. type="image/svg+xml") so crawlers skip MIME sniffing.

Labels

Required. Wire refuses to build without these labels. Every site must configure them explicitly: there are no hardcoded English defaults.

extra:
  wire:
    labels:
      # Article layout (required)
      on_this_page: "On this page"
      related_articles: "Related Articles"
      read_more: "Read more"
      # Discovery system (required for sites with steps.md files)
      discovery_start: "Guide me through this"
      discovery_read: "Read the full article"

For non-English sites, use translated strings:

    labels:
      on_this_page: "Auf dieser Seite"
      related_articles: "Verwandte Artikel"
      read_more: "Weiterlesen"
      discovery_start: "Führe mich durch"
      discovery_read: "Ganzen Artikel lesen"

Subscribe Form

Add an inline newsletter form above article content and in the footer:

extra:
  wire:
    subscribe:
      action: "https://api.follow.it/subscription-form/..."
      label: "Subscribe to updates"
      placeholder: "Your email address"
      button: "Subscribe"

Wire Settings Reference

All settings under extra.wire are optional unless marked otherwise. Defaults are shown.

News Freshness

refresh_days:
  products: 21       # Check every 3 weeks
  services: 60       # Every 2 months
  guides: 120        # Every 4 months
  comparisons: 0     # Never (auto-generated)
default_refresh_days: 21  # Fallback for unknown topics

Set a topic to 0 to disable news gathering entirely. This is useful for auto-generated content (comparisons, hub pages) that should not receive news updates.

Reword Tiers

reword_tiers:
  full: 20    # Top 20% get full SEO rewrite
  light: 30   # Next 30% get title + description only
  # Bottom 50% are skipped

Adjust these percentages based on your editorial capacity. More aggressive tiers (full: 40, light: 40) cost more but touch more pages. Conservative tiers (full: 10, light: 20) save budget.

AI Models

quality_model: claude-sonnet-4-6       # Refine, create, SEO, compare - writing tasks
simple_model: claude-haiku-4-5-20251001  # News evaluation - extraction tasks

Wire uses the API when ANTHROPIC_API_KEY is set. This is recommended because it avoids subprocess overhead. Falls back to Claude CLI (claude login) when no API key is available.

All claude_text() calls require an explicit model= parameter. Wire refuses to guess. The caller decides whether the task needs quality or speed. For the per-command mapping (which command runs quality_model, which runs simple_model, which pins its own model), see the workflow guide.

Content Limits

Setting Default What it controls
max_articles 20 Maximum articles fetched per news search
rate_limit_delay 1 Seconds between API calls
min_opportunity_score 15 Minimum score for keyword opportunities
newsweek_batch_chars 150000 Max characters per newsweek extract batch
newsweek_max_news_age_days 14 Maximum age of news articles for newsweek reports
image_style "" Style prompt for AI image generation (applied to all !makeIMG outputs)
image_sizes {default: [1024,576], wide: [1440,480], square: [512,512]} Custom dimension presets for !makeIMG
issues_repo none GitHub repo for filing issues via Wire skills (e.g. org/repo)
form_id "" Formspark form handler ID. Enables <form> submission without custom code.

Environment Variables

Set these in .env in the Wire installation directory.

Variable Required Purpose
ANTHROPIC_API_KEY Yes Claude API access
BFL_API_KEY For images AI image generation via BFL/FLUX (api.bfl.ai)
GOOGLE_CLIENT_ID For GSC Google OAuth client ID
GOOGLE_CLIENT_SECRET For GSC Google OAuth client secret

Prompt Overrides

Wire looks for prompt files in your docs directory before falling back to built-in prompts. Place these files to customize Claude's behavior.

File Location Purpose
_styleguide.md docs/ Site-wide editorial rules (prepended to all prompts)
_create.md docs/{topic}/ Custom create prompt for a topic
_update.md docs/{topic}/ Custom update/refine prompt
_seo.md docs/{topic}/ Custom SEO reword prompt
_expand.md docs/{topic}/ Custom expand prompt

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

Theming: Customize the Look

Wire's CSS uses CSS custom properties (variables) for all visual tokens. You change the look of your entire site by setting a few values in wire.yml. No CSS editing required.

theme:
  primary_color: "#059669"        # Links, buttons, active states
  accent_color: "#f59e0b"         # Highlights, accents
  text_color: "#1a1a2e"           # Body text
  font_family: "'Inter', sans-serif"
  code_font: "'JetBrains Mono', monospace"
  og_image: assets/images/social.png  # Site-wide fallback for social sharing

Wire injects these as CSS custom properties into every page. The base stylesheet reads from these variables, so one change propagates everywhere.

How it works

The base.html template generates a <style> block from your theme config:

<style>
  :root {
    --primary: #059669;
    --accent: #f59e0b;
  }
</style>

This overrides the defaults in wire.css. You never edit the CSS file directly. You configure through wire.yml.

Available CSS variables

Core colors (set via wire.yml theme:):

Variable Default What it controls
--primary #1d4ed8 Links, buttons, active nav items, logo
--primary-dark auto (80% + black) Hover states for primary elements
--primary-light auto (12% + white) Active nav background, callout background
--on-primary #fff Text color on primary backgrounds. Override if your primary is light
--accent #047857 Selection highlight, command prompt, success states
--accent-light auto (12% + white) Success form background
--text #1c1917 Body text, headings
--text-muted #57534e Secondary text, sidebar labels
--text-light #78716c Tertiary text, list markers
--bg #fafaf9 Page background
--bg-subtle #f5f5f4 Sidebar, hero sections, subtle backgrounds
--border #e7e5e4 Borders, table lines, dividers
--code-bg #1c1917 Code block background (dark)
--code-text #e7e5e4 Code block text (light)
--radius 0px Border radius on cards, code blocks, buttons

Footer (override for light footer themes):

Variable Default What it controls
--footer-bg auto (12% primary + dark) Footer background
--footer-text --code-text Footer body text
--footer-text-muted auto (65% footer-text) Footer secondary text, link text
--footer-heading #fff Footer headings, hover states
--footer-border rgba(255,255,255,0.12) Footer divider lines

Custom CSS (extra_css)

For changes beyond what CSS variables cover, add custom CSS files:

extra_css:
  - assets/css/brand.css

Wire loads your files after wire.css, so your rules override defaults. Create your CSS file in docs/assets/css/. No template editing needed.

Light footer example (docs/assets/css/brand.css):

:root {
  --footer-bg: var(--bg-subtle);
  --footer-text: var(--text);
  --footer-text-muted: var(--text-muted);
  --footer-heading: var(--text);
  --footer-border: var(--border);
}

Light primary with dark text (for brands with pastel primaries):

:root {
  --primary: #93c5fd;
  --on-primary: #1c1917;
}

Head Injection (extra_head)

Inject raw HTML into the <head> of every page. Use this for analytics, tracking pixels, or third-party scripts that must load before the page renders.

extra_head:
  - '<script>(function(c,l,a,r,i,t,y){c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);})(window,document,"clarity","script","YOUR_ID");</script>'

Each entry is a raw HTML string injected into <head> after CSS and theme variables. Wire does not validate or escape the content. Use single quotes around the YAML value to avoid conflicts with double quotes in the script.

Example: Agency with teal brand

theme:
  primary_color: "#0d9488"
  accent_color: "#f59e0b"
  font_family: "'Source Sans Pro', sans-serif"

Three lines. The entire site matches the brand. No CSS editing, no designer needed.

Frontmatter-Driven Metadata

Pages can override metadata defaults through frontmatter:

---
title: About Us
description: Learn about our team and mission.
short_title: About        # Required on all topic pages (max 20 chars)
layout: page              # Required on parent pages with child dirs
og_type: website          # Default: article
template: custom.html     # Default: page.html
---

Required frontmatter (build refuses without these):

Field Required on Purpose
title All pages Page title for <title> tag and H1
description All pages Meta description for search results
short_title All topic pages (index + content) Nav tab label (index pages) or sidebar label (content pages). Max 20 characters. No fallback to title
layout Parent index.md pages with child content dirs Prevents wrong template. Valid: page, article, landing, raw, home
created Content pages (topic + slug) Publication date for JSON-LD, RSS, sitemap (warning, not hard error)

The og_type field controls the Open Graph type meta tag. Most pages should use article (the default). Set website for the homepage, product for product pages.

Social Sharing Image (og:image)

Wire resolves og:image with a 3-tier fallback:

  1. Frontmatter image:: per-page override (highest priority)
  2. First <img> in page body: automatic extraction
  3. theme.og_image: site-wide default from wire.yml

If all three miss, no og:image tag is emitted and social shares (LinkedIn, Twitter, Slack) show a blank preview. RULE-65 flags pages without og:image during lint.

Set a site-wide fallback to cover pages without images:

theme:
  og_image: assets/images/social.png

The template field lets individual pages use different Jinja2 templates. This is useful for landing pages, contact forms, or any page that needs a different layout.

Page Layouts

Every page has a layout that controls its structure. Content pages (pages with a topic and slug, like docs/guides/seo-reference/index.md) auto-default to article. But parent pages (topic indices, the homepage, or any index.md with child directories) must declare their layout explicitly. Wire refuses to build without it.

Add layout: to your frontmatter:

---
title: All Guides
description: Everything you need to get started.
layout: page
short_title: Guides
---

Available layouts:

Layout Use for What it does
page Topic index pages, about pages Clean page with nav, no sidebar or reading progress
article Content pages (auto-default) 3-column: TOC, content, sidebar CTA + reading progress bar
landing Marketing/sales pages Full freedom, no width constraints, no injected H1. Splits at <hr> into hero/light sections. Custom hero: add section-hero to your <section> to bypass Wire's wrapper (RULE-64)
raw Embeds, widgets, iframes Bare HTML output, no header/footer/nav chrome
home Homepage Hero section with site introduction

Wire is opinionated about this: if you have docs/guides/index.md with child directories like docs/guides/seo-reference/, that index page must set layout: page (or another layout). Without it, the build fails with a clear error telling you which pages need fixing.

Build Configuration

The build system reads from the same wire.yml:

Setting Default Purpose
docs_dir docs Markdown source directory
templates_dir templates Jinja2 templates directory
output_dir site HTML output directory
exclude (see above) Regex patterns for files to skip

nav is required in wire.yml. Wire does not guess your site structure. Navigation is a strategic decision. Define every section and page explicitly.

nav:
  - index.md
  - Insights:
    - Content Strategy: insights/content-strategy/index.md

Every nav item includes title, url, and description from the page's frontmatter. Templates can access description to build mega menus, topic grids, or any navigation that shows context beyond just titles. For sections, the description comes from the section's index page.

Auto News Nav

When docs/news/ exists and contains articles (subdirectories with index.md), Wire automatically appends it as the last nav item. No configuration needed.

  • Has articles - appears last in nav (label from news/index.md short_title)
  • Empty or missing - nothing changes
  • Exclude it: add nav_exclude: [news] to wire.yml

Wire also auto-generates a news listing page at /news/ showing each article's title, first 120 characters of the first paragraph, author name, and publish date. Each article gets NewsArticle JSON-LD. No docs/news/index.md needed.

Note: news files inside topic subdirectories (e.g. docs/seo/chatgpt/news/) are never built as pages. They are internal storage for the Chief pipeline. Only top-level docs/news/ articles appear in the listing.

Copy Dirs

Copy directories verbatim from your docs folder to the output. Useful for standalone HTML tools, JavaScript apps, or any content that should not be processed as markdown.

copy_dirs:
  - vendor-finder      # Copies docs/vendor-finder/ -> site/vendor-finder/
  - tools/calculator   # Nested paths work

Missing source directories are skipped with a warning. The build continues.

CTA Injection

Append HTML blocks to pages in specific topics. Useful for topic-specific calls to action, signup forms, or promotional content.

extra:
  wire:
    cta:
      services: '<div class="cta">Need help? <a href="/contact/">Contact us</a></div>'
      guides: '<div class="cta">Want a demo? <a href="/demo/">Book now</a></div>'

The CTA HTML is appended to the rendered content of every page in the matching topic (except topic index pages). This keeps the CTA out of your markdown files and centralizes it in config.

Raw Markdown Export

Export stripped-down markdown files alongside the HTML build. Useful for chatbot training data, API documentation, or machine-readable content feeds.

extra:
  wire:
    raw_export:
      - bots/index.md    # Exported as site/bots.md

The export strips YAML frontmatter and converts Unicode characters (smart quotes, em dashes, arrows) to ASCII equivalents. The output path maps {topic}/index.md to {topic}.md for cleaner URLs.

JSON-LD Schema Types

Wire auto-generates JSON-LD structured data for every page. The schema type is selected based on frontmatter and URL patterns:

Condition Schema Type
Homepage WebSite
Topic index (no slug) CollectionPage
schema_type: Organization or company: in frontmatter Organization + SoftwareApplication
/news/ URL or date-pattern slug NewsArticle
/authors/ URL ProfilePage with Person
schema_type: TechArticle in frontmatter TechArticle
Default Article

Set schema_type in frontmatter to override the automatic detection.

Redirects

When you restructure pages (move into topic directories, rename slugs), tell Wire about the old URLs so GSC data follows the pages. Each redirect has a from, an optional to, and a status code:

redirects:
  # 301 Moved Permanently (default when 'to' is present)
  - from: /old-path/
    to: /new/path/
  - from: /de/artikel/
    to: /de/guides/artikel/
    status: 301

  # 410 Gone - page permanently removed, tell Google to deindex
  - from: /deleted-page/
    status: 410

The old dict format (/old/: /new/) still works but does not support status codes.

Wire reads redirects from two sources and merges them:

  1. wire.yml redirects: key (user-configured, for site restructures)
  2. .wire/redirects.yml (auto-created by Wire when pages are moved/merged)

At build time, Wire generates:

  • _redirects file (Netlify/Cloudflare format) with status codes
  • HTML fallback pages (meta-refresh for 301, "Gone" page for 410)
  • .htaccess rules when deploy.target: apache (RewriteRule for 301, [G] flag for 410)

After adding redirects, run python -m wire.chief migrate-gsc to rekey the GSC database. The audit warns about GSC URLs that have no matching page and no redirect; these are URLs where Google still sends traffic but gets a 404.

Database Location

The GSC database lives at {site_dir}/.wire/gsc.db. This directory is created automatically on first data run. Add .wire/ to your .gitignore.

Progress tracking files for batch operations also live in .wire/:

.wire/
  gsc.db                              # GSC keyword database
  progress-news-products.json         # Batch progress tracking
  progress-refine-products.json
  newsweek_extracts_2026-03-10.md     # Cached newsweek extracts

Related: getting started.

See the Guides overview for all Wire documentation.