WingTip

Open-source, SEO-first documentation sites from Markdown.

WingTip social card

Live demo · Migration guide · Source · Roadmap

WingTip turns a repository README.md and docs/ directory into fast, portable static documentation. It generates crawlable HTML, search and discovery metadata, structured data, machine-readable Markdown artifacts, and an offline-capable site without requiring a hosted documentation platform.

Start with zero configuration, customize when needed, and deploy the generated files anywhere.


Why WingTip

Moving from hosted documentation?

Use the migration guide to assess what WingTip supports today, preserve URLs and metadata, validate generated output, and plan a safe cutover. Public repositories and sanitized reproductions can request a structured migration review.

Features

Search, SEO, and machine-readable output

Documentation experience

Performance, security, and extensibility


Installation

Python 3.9 or newer is required.

pip install wingtip

Install the optional live server:

pip install "wingtip[serve]"

For local development from a clone:

pip install -e ".[dev]"

Quickstart

Create a project containing README.md and, optionally, a docs/ directory:

your-project/
├── README.md
├── docs/
│   ├── guide.md
│   └── api.md
├── config.json       # optional
├── theme.json        # optional
└── favicon.png       # optional; enables favicon and PWA icon generation

Run WingTip from the project directory:

wingtip

The default output is docs/site. To build another source directory into a chosen destination:

wingtip --source ./your-project --output ./build

Start the live development server after building:

wingtip --serve

Use wingtip --help for all CLI options.


Configuration

Configuration is optional. Without config.json, WingTip derives the project name from the README.md heading or source-directory name and uses relative URLs for local portability.

Add config.json when you want production URLs, repository links, analytics, security policy, or social-card customization:

{
  "base_url": "https://docs.example.com",
  "project_name": "Acme API",
  "version": "1.0.0",
  "description": "Integration documentation for the Acme API.",
  "author": "Acme",
  "repo_url": "https://github.com/acme/api-docs",
  "og_image": "social-card.png",
  "twitter_handle": "@acme",
  "github": {
    "repo": "acme/api-docs",
    "branch": "main"
  },
  "analytics": {
    "provider": "plausible",
    "domain": "docs.example.com"
  },
  "csp": true,
  "social_card": {
    "title": "Acme API",
    "tagline": "Build with Acme.",
    "theme": "light",
    "font": "Poppins"
  }
}

Place a local favicon.png in the project root to emit favicon/nav-logo markup and generate 192×192 and 512×512 PWA icons. If it is absent, WingTip emits none of those branded assets.

Per-page frontmatter

Use YAML frontmatter to control individual pages:

---
title: Authentication API
description: Authenticate server-side requests to the Acme API.
keywords:
  - API authentication
  - OAuth
canonical: https://docs.example.com/authentication
noindex: false
author: Acme Developer Relations
date: 2026-07-16
lastmod: 2026-07-17
category: API reference
version: v2
lang: en
translations:
  es: https://docs.example.com/es/authentication
og_title: Acme API authentication
twitter_description: Implement Acme API authentication.
---

Noindexed pages are excluded from the sitemap, search index, category/version indexes, and structured data.

Plugins and custom Markdown

Place Python modules in plugins/. WingTip can auto-load every module or load only names listed in the plugins array in config.json.

Plugins can expose:

Hook failures are reported as warnings so one extension does not silently stop the entire build.

Build auditing

The repository includes a post-build auditor used by CI:

python audit_site.py --output docs/site --source .

It exits non-zero when it finds:

CI also runs a negative fixture that deliberately injects a broken asset reference and verifies that the auditor fails.


GitHub Pages deployment

The included GitHub Actions workflow builds and deploys on pushes to main. For another repository, the essential build steps are:

- uses: actions/setup-python@v5
  with:
    python-version: "3.12"
- run: pip install wingtip
- run: wingtip
- uses: actions/upload-pages-artifact@v3
  with:
    path: docs/site

Set base_url to the final Pages URL so canonical, sitemap, feed, social, and alternate URLs are absolute in production.


Social cards

WingTip generates social-card.png during a build. Force regeneration after changing card settings:

wingtip --regen-card

The social_card object supports title, tagline, light/dark style, font, and an optional logo. Per-page og_image and twitter_image frontmatter can override the site image.


Custom 404 page

Create 404.md in the project root. WingTip converts it to 404.html with the same Markdown processing and site template as other pages:

---
permalink: /404.html
noindex: true
---

# Page not found

The requested documentation page does not exist.

Generated output

A normal build includes:

docs/site/
├── index.html
├── guide.html
├── guide.html.md
├── search_index.json
├── sitemap.xml
├── robots.txt
├── feed.xml
├── llms.txt
├── llms-full.txt
├── manifest.json
├── sw.js
├── offline.html
├── social-card.png
├── syntax.css
└── static/

categories.json and versions.json are emitted when pages declare those values. favicon.png, icon-192.png, and icon-512.png are emitted only when the project supplies a favicon.

Current limitations and roadmap

Mermaid diagrams, broad MDX compatibility, an automated hosted-platform importer, and a theme marketplace are not yet built.

See the roadmap and feature comparison for planned work.


License

MIT. Use freely. Modify ruthlessly.