On this page
- wire.yml: Site Configuration
- Header: Two-Row Navigation
- offerings
- links
- cta
- Navigation Validation
- Search
- Sidebar CTA (Required)
- Article Bottom CTA
- Multi-Language CTA
- Footer
- Logo and Favicon
- Labels
- Subscribe Form
- Wire Settings Reference
- News Freshness
- Reword Tiers
- AI Models
- Content Limits
- Environment Variables
- Prompt Overrides
- Theming: Customize the Look
- How it works
- Available CSS variables
- Custom CSS (extra_css)
- Head Injection (extra_head)
- Example: Agency with teal brand
- Frontmatter-Driven Metadata
- Social Sharing Image (og:image)
- Page Layouts
- Build Configuration
- Navigation
- Copy Dirs
- CTA Injection
- Raw Markdown Export
- JSON-LD Schema Types
- Redirects
- Database Location
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/
links
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.
Navigation Validation
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.
Search
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
Sidebar CTA (Required)
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
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:
- Frontmatter
image:: per-page override (highest priority) - First
<img>in page body: automatic extraction 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 |
Navigation
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.mdshort_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:
wire.yml redirects:key (user-configured, for site restructures).wire/redirects.yml(auto-created by Wire when pages are moved/merged)
At build time, Wire generates:
_redirectsfile (Netlify/Cloudflare format) with status codes- HTML fallback pages (meta-refresh for 301, "Gone" page for 410)
.htaccessrules whendeploy.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.