A static site generator for documentation that is built to be indexed and cited.
Project description
WingTip
Open-source, SEO-first documentation sites from Markdown.
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
- Own the output: Build ordinary HTML, CSS, JavaScript, feeds, and metadata that can be hosted on any static file server.
- Built for discovery: Generate canonical URLs, robots directives, sitemap metadata, Open Graph and Twitter cards,
TechArticleand breadcrumb JSON-LD, RSS, and hreflang alternates. - Built for AI retrieval: Publish
llms.txt, full concatenated documentation, and a Markdown alternate beside every generated page. - No mandatory CDN runtime: Core styles, scripts, icons, KaTeX, and fonts are vendored into the Python package and copied into the build. External analytics remain opt-in.
- Your branding only: No "powered by" badge, injected links, or generator watermarks — the generated site carries your identity, not WingTip's.
- Zero infrastructure: Search, navigation, PWA support, and offline fallback work from static hosting.
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
- Per-page
title,description,keywords, canonical URL, robots/noindex, language, Open Graph, and Twitter overrides - Automatic description fallback from the first paragraph
TechArticleandBreadcrumbListJSON-LDsitemap.xml,robots.txt, RSS,llms.txt, and full concatenated documentation- Raw Markdown alternates emitted as
.html.md - Published/updated dates with Git-based modified-date fallback
- Per-page categories and versions, plus generated
categories.jsonandversions.json - Per-page language and translation mappings with
hreflangandx-default - Local client-side full-text search with keyboard navigation (details)
Documentation experience
README.mdbecomesindex.html;docs/is discovered recursively with nested paths preserved in URLs (docs/guides/intro.md→guides/intro.html)- Automatic sidebar with collapsible directory groups (
_category.jsonfor names and ordering,orderfrontmatter for pages), table of contents, and previous/next navigation - GitHub “Edit this page” links
- Responsive layout with light/dark mode and screen-reader/keyboard support
- Pygments syntax highlighting and copy-to-clipboard controls
- Tables, footnotes, definition lists, attributes, admonitions, and Markdown inside HTML
- KaTeX math rendering (examples)
- Configurable external-link handling and correct
.mdlink rewriting, including fragments and queries - Custom Markdown-based
404.html
Performance, security, and extensibility
- Local image copying, lazy loading, intrinsic dimensions, and responsive
srcsetgeneration - Locally vendored core frontend assets
- PWA manifest, service worker, precache, and offline fallback
- PWA icons generated only from a project-supplied
favicon.png - Optional generated or custom Content Security Policy
- Plausible, Umami, Fathom, Google Analytics, custom analytics, and global/per-page
<head>snippets - Plugin hooks before/after builds and conversions, plus plugin-provided Python-Markdown extensions
- Theme variables through
theme.jsonand static CSS overrides (theming guide) - Live development server with auto-reload and scroll restoration
- Post-build auditor for missing local files, unexpected CDN references, required artifacts, and branding leaks
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:
before_build(config, output_dir)before_convert(frontmatter, markdown, input_path, output_path)after_convert(html, frontmatter, input_path, output_path)after_build(config, output_dir)markdown_extensions, as a list or callable returning Python-Markdown extensions
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:
- Missing local files referenced by generated HTML
- Known CDN origins for dependencies that WingTip vendors locally
- Missing required search, SEO, feed, or PWA artifacts
- Missing PWA icons when a project favicon was supplied
- Output assets byte-identical to packaged branding assets
- WingTip branding in a project whose configured name is not WingTip
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file wingtip-0.6.3.tar.gz.
File metadata
- Download URL: wingtip-0.6.3.tar.gz
- Upload date:
- Size: 625.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f97f269008204d148c80b526263833fa824d56bdd3e2bb808ed729629ac6d10
|
|
| MD5 |
c2745ab662aa5446db5d9ac17a323b24
|
|
| BLAKE2b-256 |
9e2f9640df5500138037cac9b1b21af68c50c5f2c908e881f2e1620c0ea4ecc5
|
Provenance
The following attestation bundles were made for wingtip-0.6.3.tar.gz:
Publisher:
publish.yml on semanticentity/WingTip-Static-Site-Generator
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wingtip-0.6.3.tar.gz -
Subject digest:
3f97f269008204d148c80b526263833fa824d56bdd3e2bb808ed729629ac6d10 - Sigstore transparency entry: 2193474000
- Sigstore integration time:
-
Permalink:
semanticentity/WingTip-Static-Site-Generator@0c559f57a706607ee5f6d477050d8a1200c22194 -
Branch / Tag:
refs/tags/v0.6.3 - Owner: https://github.com/semanticentity
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0c559f57a706607ee5f6d477050d8a1200c22194 -
Trigger Event:
release
-
Statement type:
File details
Details for the file wingtip-0.6.3-py3-none-any.whl.
File metadata
- Download URL: wingtip-0.6.3-py3-none-any.whl
- Upload date:
- Size: 629.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
75067450717ffa9cad17218f8413699508addcf2d128aa8ad9cc85b1eae6b502
|
|
| MD5 |
97eca3bc5b3c8a8039d5748fde6b5378
|
|
| BLAKE2b-256 |
b12878da69d420bd30349a49d5f9cb36c0f47cce79c0b34d84ed563fb2afd544
|
Provenance
The following attestation bundles were made for wingtip-0.6.3-py3-none-any.whl:
Publisher:
publish.yml on semanticentity/WingTip-Static-Site-Generator
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wingtip-0.6.3-py3-none-any.whl -
Subject digest:
75067450717ffa9cad17218f8413699508addcf2d128aa8ad9cc85b1eae6b502 - Sigstore transparency entry: 2193474008
- Sigstore integration time:
-
Permalink:
semanticentity/WingTip-Static-Site-Generator@0c559f57a706607ee5f6d477050d8a1200c22194 -
Branch / Tag:
refs/tags/v0.6.3 - Owner: https://github.com/semanticentity
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0c559f57a706607ee5f6d477050d8a1200c22194 -
Trigger Event:
release
-
Statement type: