--- File: README.md --- # WingTip **Open-source, SEO-first documentation sites from Markdown.**  [Live demo](https://semanticentity.github.io/WingTip-Static-Site-Generator) · [Migration guide](docs/migration.md) · [Source](https://github.com/semanticentity/WingTip-Static-Site-Generator) · [Roadmap](docs/roadmap.md) 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, `TechArticle` and 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](docs/migration.md) 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](https://github.com/semanticentity/WingTip-Static-Site-Generator/issues/new?template=migration.yml). ## 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 - `TechArticle` and `BreadcrumbList` JSON-LD - `sitemap.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.json` and `versions.json` - Per-page language and translation mappings with `hreflang` and `x-default` - Local client-side full-text search with keyboard navigation ([details](docs/search-features.md)) ### Documentation experience - `README.md` becomes `index.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.json` for names and ordering, `order` frontmatter 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](docs/math-examples.md)) - Configurable external-link handling and correct `.md` link rewriting, including fragments and queries - Custom Markdown-based `404.html` ### Performance, security, and extensibility - Local image copying, lazy loading, intrinsic dimensions, and responsive `srcset` generation - 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 `
` snippets - Plugin hooks before/after builds and conversions, plus plugin-provided Python-Markdown extensions - Theme variables through `theme.json` and static CSS overrides ([theming guide](docs/theming.md)) - 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. ```bash pip install wingtip ``` Install the optional live server: ```bash pip install "wingtip[serve]" ``` For local development from a clone: ```bash pip install -e ".[dev]" ``` ## Quickstart Create a project containing `README.md` and, optionally, a `docs/` directory: ```text 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: ```bash wingtip ``` The default output is `docs/site`. To build another source directory into a chosen destination: ```bash wingtip --source ./your-project --output ./build ``` Start the live development server after building: ```bash 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: ```json { "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: ```yaml --- 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: ```bash 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: ```yaml - 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: ```bash 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: ```markdown --- permalink: /404.html noindex: true --- # Page not found The requested documentation page does not exist. ``` --- ## Generated output A normal build includes: ```text 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](docs/roadmap.md) for planned work. --- ## License MIT. Use freely. Modify ruthlessly. --- File: docs/admonitions.md --- # Admonition Examples WingTip supports admonition blocks to highlight important information. These are special callout blocks that can be used to draw attention to specific content. ## Basic Usage Use `!!!` followed by the type of admonition to create a block: !!! note This is a simple note admonition. It can contain multiple paragraphs and other Markdown elements. - Lists - Code blocks - etc. ## Available Types ### Note !!! note This is a note admonition. Use it for general information. ### Warning !!! warning This is a warning admonition. Use it to warn users about potential issues. ### Danger !!! danger This is a danger admonition. Use it for critical warnings or dangerous operations. ### Tip !!! tip This is a tip admonition. Use it for helpful suggestions and best practices. ### Info !!! info This is an info admonition. Use it for additional context or background information. ### Success !!! success This is a success admonition. Use it to highlight positive outcomes or completion states. ## Advanced Usage ### Nested Content Admonitions can contain any Markdown content: !!! note ### A Header Inside an Admonition 1. Ordered lists work great 2. Code blocks work too: ```python def hello(): print("Hello from an admonition!") ``` Tables work when not nested in lists: | Column 1 | Column 2 | |----------|----------| | Cell 1 | Cell 2 | ### Custom Titles You can add custom titles to admonitions: !!! tip "Custom Title" This tip has a custom title! ## Dark Mode Support All admonitions automatically adapt to dark mode when the theme is switched, maintaining readability and consistent styling with the rest of the content. --- File: docs/changelog.md --- # WingTip Changelog ## [v0.6.5] - 2026-07-18 ### Redirects - `config.json` accepts `"redirects": [{"from": "/old-path", "to": "/new-path"}]`. Every build emits a static redirect page per rule (instant redirect with a visible fallback link — works on GitHub Pages and any static host) plus a `_redirects` file in Netlify/Cloudflare Pages format. Platform wildcard patterns (`:slug*`) are translated to splats and covered host-level. Redirect stubs are `noindex` and stay out of the sitemap and search index; collisions with real pages and missing targets warn at build time. - `wingtip migrate` carries the source platform's redirects into the new project's `config.json` — previously they were only listed in the migration report as manual work. Non-wildcard rules now count as converted. ### Fixed - Search on configured-`base_url` sites fetched its index from the absolute base URL, so previews, mirrors, and local serves of the built site broke search with a cross-origin error. The index is now fetched relative to the page, working on the canonical domain and any same-origin copy alike. - The search error message met neither light- nor dark-theme contrast requirements; it is now themed and AA-compliant. ## [v0.6.4] - 2026-07-18 ### Navigation - Wide desktop (≥1200px) pins the site nav open as a persistent left sidebar: no interaction needed, the hamburger hides, and the logo reverts to a plain home link. Below 1200px the toggle behavior is unchanged. Content centers between the left nav and the right table of contents with a 900px reading measure. - Visible breadcrumb trail on every non-home page — Home › directory groups (named via `_category.json`) or frontmatter category › page title — alongside the existing JSON-LD breadcrumbs. - The pinned sidebar scrolls the active page into view when it sits below the fold. - Sidebar groups already auto-collapse to the active branch; now documented behavior. ### Section hub pages - `_category.json` accepts `"index": true`: the directory gets a generated landing page listing its pages (with frontmatter descriptions) and nested groups. A source `index.md` always wins. Hubs appear in the sitemap, search index, and AI artifacts, gain an **Overview** link in their nav group, and breadcrumb directory crumbs link to them. ### SEO - `og:url`, `og:image`, and `twitter:image` (plus the card type that depends on the image) are emitted only when absolute, as the OpenGraph spec requires — zero-config builds previously shipped relative values that scrapers ignore. Configured-`base_url` sites are unchanged. - The post-build audit now resolves same-origin absolute URLs against the local build instead of skipping them as external, closing the blind spot that let a dead reference survive on configured-base sites. ## [v0.6.3] - 2026-07-17 ### GitHub-flavored Markdown - Task lists (`- [ ]` / `- [x]`) render as checkboxes instead of literal brackets; each checkbox is label-wrapped so it carries its item text as an accessible name. - GitHub alerts (`> [!NOTE]`, `[!TIP]`, `[!IMPORTANT]`, `[!WARNING]`, `[!CAUTION]`) render as styled admonitions; adjacent alert blocks that python-markdown merges into one blockquote are split back apart. - Bare `http(s)://` and `www.` URLs in prose autolink, with trailing punctuation kept outside the link. - Search-index text extraction now uses the same Markdown pipeline as page rendering: fence markers, fence language tags, table pipe rows, and task markers no longer leak into search snippets. ### Navigation - The site nav no longer depends on clicking the logo: an always-present hamburger button toggles it (sites without a favicon previously had no header navigation at all), the logo now toggles instead of only opening, and `aria-expanded` is tracked. - Categorized sites: the slideout now clones the entire navigation (one list per category plus headings) instead of only the first list, with styled category headings and nested groups. - The mobile table-of-contents button worked for the first time: it was positioned underneath the fixed header and its click handler was never attached. Now placed below the header and wired up. - Client-side TOC generation no longer overwrites the build's heading ids, which had recreated duplicate anchors (`#setup` twice) and mangled unicode slugs; the TOC also indexes only content headings, not navigation headings. ### Theming - Light mode was unreadable in the header: the navbar title and every slideout link were hardcoded white on a background that flips to white. Nav colors are now paired variables. - Manually toggling the theme now recolors the navbar too — previously it only tracked the OS preference, producing a white navbar on a dark page. ### Accessibility - Zero axe-core violations across every generated page in both color schemes, enforced in CI by a new `audit_a11y.js` gate (with a negative test, like the existing audit). - Skip-to-content link; the closed slideout's links no longer occupy the tab order (keyboard users previously tabbed through the entire site nav to reach search); focus moves into the nav on open and back to the toggle on close. - Landmarks and labels: header/banner, labeled navs, `role=search`, named theme toggle; decorative logo alt. - WCAG AA contrast: admonition titles, code tokens, footer text, and the light-theme link color; content links are underlined rather than color-only. - Code blocks are keyboard-scrollable (`tabindex="0"`); `prefers-reduced-motion` collapses all animation. ### PWA and artifacts - The offline fallback page is now actually precached — the service worker referenced `offline.html` but built its cache list before the file was written, so offline navigation to an uncached URL had always shown the browser error page. - `noindex` frontmatter is honored by `llms.txt`, `llms-full.txt`, and `skill.md`, matching the search index and sitemap. - Projects without a root `404.md` get a default styled 404 page; the raw-Markdown alternate (`.html.md`) is written for every page, fixing the dead alternate link on 404 pages. - Sites without a `repo_url` no longer render an empty GitHub link in the footer. ## [v0.6.2] - 2026-07-17 - GFM strikethrough support: `~~text~~` renders as `', html_content, re.DOTALL) total_lines = sum(block.count('\n') + 1 for block in code_blocks) stats_html = f'(.*?)
This page contains {total_lines} lines of code.
' return html_content + stats_html Plugin = CodeStatsPlugin ``` ## Best Practices 1. **Documentation**: Include docstrings and comments explaining your plugin's purpose and configuration options 2. **Error Handling**: Gracefully handle errors and edge cases 3. **Performance**: Keep modifications efficient, especially for large sites 4. **Testing**: Test your plugin with various content types and edge cases ## Plugin API Reference ### Hook Methods #### before_markdown_conversion - **Parameters**: - `md_content`: Raw markdown content - `metadata`: Page metadata from frontmatter - `filepath`: Source markdown file path - **Returns**: Modified markdown content #### after_html_generation - **Parameters**: - `html_content`: Generated HTML content - `metadata`: Page metadata - `filepath`: Source file path - **Returns**: Modified HTML content #### after_full_page_assembly - **Parameters**: - `final_html`: Complete page HTML - `metadata`: Page metadata - `output_filepath`: Output file path - **Returns**: Modified page HTML ### Configuration Plugins can access their configuration through `self.config` in the plugin class. The configuration is loaded from `config.json`. --- File: docs/quickstart.md --- # Quick Start Add beautiful documentation to your project in under 5 minutes. ## 1. Install WingTip (2 min) ```bash # In your project directory: git clone https://github.com/SemanticEntity/WingTip.git pip install -r WingTip/requirements.txt ``` ## 2. Add Your Docs (1 min) ``` your-project/ ├── README.md # Becomes the homepage └── docs/ # Add .md files for documentation └── guide.md ``` ## 3. Configure (Optional, 30s) Create `config.json` in your project root: ```json { "project": "Your Project", "description": "Your project description", "github": { "repo": "username/repo", "branch": "main" } } ``` ## 4. Generate and Preview (10s) ```bash python wingtip/main.py # Build the site python wingtip/serve.py # Start local dev server with live reload ``` Visit `http://localhost:8000` in your browser. ## 5. Deploy to GitHub Pages (1 min) 1. Push your changes to GitHub 2. Go to **Settings → Pages** 3. Set branch to `main` and folder to `/docs/site` 4. Your documentation will be published to `https://username.github.io/repo` --- Your docs now include: * Responsive layout with light/dark mode * Mobile-friendly sidebar and TOC * SEO-optimized output and social cards * GitHub "Edit this page" links * Instant preview with live reload No build tools. No config lock-in. Just Markdown in, HTML out. --- File: docs/roadmap.md --- # WingTip Roadmap ## Objective Make WingTip the most reliable way to move a documentation project from a hosted platform to portable static output: migrate an existing repository, preserve its information architecture and URLs, and prove the result with automated search, performance, and integrity audits. WingTip will not try to reproduce every hosted collaboration feature. It will compete on ownership, migration quality, technical discovery, build transparency, portability, and zero mandatory platform cost. ## Current position Status reflects the repository as of July 18, 2026. Competitor capabilities change; any public comparison must be generated from a reproducible fixture rather than unsupported marketing claims. | Capability | WingTip now | Competitive status | Priority | | --- | --- | --- | --- | | Portable static HTML output | Yes | Leadership target | Maintain | | No mandatory hosted runtime | Yes | Leadership target | Maintain | | No mandatory CDN frontend assets | Yes | Leadership target | Maintain | | No imposed generator branding | Yes | Leadership target | Maintain | | Canonical, robots, sitemap, RSS, OG/Twitter | Yes | Strong parity | Maintain | | `TechArticle` and breadcrumb JSON-LD | Yes | Strong parity | Expand validation | | `llms.txt`, full docs, Markdown alternates | Yes | Strong parity | Add agent skills | | Per-page noindex, dates, language, category, version | Yes | Strong parity | Improve UI | | Hreflang alternates | Yes | Search differentiator | Add cluster audit | | Local search | Yes | Basic parity | Ranking controls | | PWA and offline fallback | Yes | Differentiator | Maintain | | Responsive image generation | Yes | Differentiator | Add budgets | | Configurable analytics, head snippets, and CSP | Yes | Strong parity | Validate policies | | Plugin hooks and Markdown extensions | Yes | Extensibility base | Formalize API | | Post-build integrity/branding audit | Yes | Leadership target | Expand | | Recursive content trees | Yes | Parity | Maintain | | Grouped, collapsible navigation | Yes | Tabs, versions, languages pending | P1 | | Redirect migration and static-host outputs | Yes | Static redirect pages + `_redirects` emitted from config; migrate carries platform rules | Expand (redirect-chain validation) | | Hosted-platform configuration import | Yes | Differentiator | Expand | | MDX compatibility analysis | Yes | Differentiator | Expand | | OpenAPI reference generation | No | Major parity blocker | P1 | | API playground | No | Major parity blocker | P1 | | Agent `skill.md` discovery | Yes | Emerging differentiator | Maintain | | Preview deployments and visual review | No | Workflow gap | P2 | | Authentication and private docs | No | Enterprise gap | P3/partner | | Hosted collaborative editor | No | Intentionally not core | Ecosystem | ## Delivery plan ### Phase 1 — Migration quality (P0) #### Content and navigation model - ✅ Recursively discover `.md` content (`.mdx` compatibility still pending) - ✅ Preserve nested source paths in generated URLs (`docs/guides/intro.md` → `guides/intro.html`) - ✅ Ordered navigation groups: `_category.json` (`name`, `order`) per directory, `order`/`nav_order` frontmatter per page - ✅ Render grouped/collapsible navigation from the directory tree - ✅ Detect duplicate output paths (collisions are warned and skipped) - ✅ GFM fidelity: task lists, GitHub alerts, strikethrough, bare-URL autolinks (July 18, 2026) - ✅ Visible breadcrumb navigation in the page body, matching the JSON-LD trail (July 18, 2026) - ✅ Section hub pages: `_category.json` `"index": true` generates a landing page per directory, with an Overview nav link and linked breadcrumbs (July 18, 2026) - ✅ Pinned left sidebar on wide desktop (≥1200px); hamburger/slideout below (July 18, 2026) - Introduce tabs, products, versions, and languages in the navigation model — design decided July 18, 2026: locale/version become first-class dimensions (one nav tree definition, per-dimension instances, scoped search, hreflang/canonical mechanics per dimension) and this moves AHEAD of generic nav sharding, because dimensions both shrink the scaling problem and unblock migration fidelity for platform configs that use them - Detect orphaned navigation entries #### Hosted-platform importer ```bash wingtip migrate ./existing-docs --output ./wingtip-docs ``` Shipped (read-only — the source project is never modified): - ✅ Read current and legacy platform configuration formats (`docs.json`, `mint.json`) - ✅ Import project name, description, brand colors, and favicon - ✅ Convert navigation groups to directory `_category.json` files and per-page `order` frontmatter - ✅ Preserve page paths in generated URLs; report every preserved URL - ✅ Rewrite platform-style absolute internal links to portable relative links - ✅ Inventory MDX components per page; strip module `import`/`export` lines and MDX comments - ✅ Approximate common MDX components (callouts → blockquotes, titled sections → labels, `Card` → link, `src`-bearing components → images) with JSX dedenting - ✅ Rewrite links in raw `href`/`src` attributes with page-relative → site-root → case-insensitive resolution - ✅ Stub dynamic link expressions and report suspected broken links in the source - ✅ Carry platform redirects into `config.json`; every build emits static redirect pages plus a Netlify/Cloudflare `_redirects` file with wildcard→splat translation (July 18, 2026) - ✅ Never silently discard unsupported configuration or content — everything unhandled is listed in the report - ✅ Validated against real public hosted-docs repositories (46 → 5,387 pages) Still pending: - Resolve local JSON `$ref` configuration - Convert tabs, products, versions, and languages beyond flat group mapping - Preserve OpenAPI references for Phase 2 endpoint rendering - Unique-basename fallback for bare links that the source platform resolved via navigation context (found at the 5,000-page tail) - Treat `snippets/` include-partials as includes (inline where referenced, or skip and report) instead of standalone pages - Copy non-image media (video, PDF, downloads) referenced by pages into the build output — currently only rendered images and `static/` ship #### Migration report - ✅ Every migration emits `migration-report.md` in the new project: an executive summary (format detected, pages converted, URLs preserved, groups mapped, manual follow-up count) followed by ✓ converted items and ⚠ manual work (components per page, unmapped groups, orphan pages, redirects, configuration not carried) and next steps Still pending: - Machine-readable JSON report alongside the Markdown - Broken links and missing assets detection at migrate time (the post-build audit covers this after `wingtip` runs) - File/line locations for component occurrences #### Migration documentation and evidence - ✅ Open-source hosted-platform migration guide (July 17, 2026) - ✅ Migration intake through a dedicated GitHub issue template (July 17, 2026) - Create a sanitized real-world hosted-docs fixture for regression testing - Record a repository-to-deployed-site migration demo - Document output ownership, supported hosts, and unsupported constructs plainly **Exit criteria:** Representative hosted-platform repositories build without lost pages, URLs, metadata, or unreported incompatibilities, and a prospective user can verify that from the published guide, fixture, and demo. ### Phase 2 — Documentation parity (P1) Prioritize capabilities that block real migrations: - OpenAPI 3.x ingestion and endpoint-page generation - API operation navigation, parameter/schema tables, examples, and code samples - Optional static-first API playground enhancement - AsyncAPI inventory and design - Tags: `tags:` frontmatter → generated per-tag index pages and a tags hub; related-pages block per page (tag overlap + directory siblings, computed at build time) - Search weighting/boost frontmatter and section-level result anchors - Visible version, product, and language switchers - Redirect validation and redirect-chain detection - Mermaid diagrams — approach decided July 18, 2026: vendor `mermaid.min.js` locally (no CDN), lazy-loaded only on pages containing diagrams; build-time SVG rejected (would add a Node dependency to a Python tool) - Common hosted-platform MDX compatibility components: cards, columns, tabs, accordions, steps, callouts, frames, and code groups - Reusable snippets/includes and content variables - Navigation banners, badges, deprecation labels, and hidden-page controls - Formal, versioned plugin API and template/theme extension points **Exit criteria:** A typical public SaaS documentation repository does not need to remain on a hosted documentation platform solely for navigation, common MDX presentation, or OpenAPI reference pages. ### Phase 3 — Search-engineering leadership (P1) Turn the existing auditor into a differentiated discovery system: - Validate titles, descriptions, canonicals, robots directives, OG/Twitter metadata, and JSON-LD - ✅ Zero-config social metadata decided and shipped: og:url/og:image/twitter:image are emitted only when absolute, per the OpenGraph spec; canonicals deliberately stay relative-self-resolving (July 18, 2026) - Detect canonical conflicts, duplicate metadata, orphan pages, broken fragments, redirect chains, and accidental noindex - Validate hreflang reciprocity, language codes, canonicals, and `x-default` clusters - Audit internal-link depth and surface pages with weak contextual connectivity - Add configurable HTML, CSS, JavaScript, image, request-count, and font performance budgets - Shard or lazy-load sidebar navigation for very large sites: per-page full navigation makes total output size quadratic in page count (measured: a 5,387-page site emits a ~5,300-entry sidebar on every page, ~3.9GB total). Design decided July 18, 2026 — "context window" nav: each page inlines ancestors + siblings + children server-side (crawlable, bounded), full tree in a shared `nav.json` hydrating the slideout on demand; hub pages keep every page within ~3 clicks. Search-index and `llms-full` sharding follow the same per-section pattern. Sequenced after the dimension model (see Phase 1) - Audit at scale: parallelize the post-build audit per file (it is embarrassingly parallel) and add incremental auditing keyed on content hash so CI re-audits only changed pages. At the 5,387-page tail the full audit takes tens of minutes — a gate that slow gets skipped, and a skipped gate protects nothing. (Typical 50–300 page sites audit in seconds.) - ✅ Same-origin absolute URLs resolve against the local build (base detected from the index canonical), closing the blind spot that hid a dead 404 Markdown alternate on the demo site (July 18, 2026) - Emit machine-readable audit output for CI annotations - Generate a crawl graph and diff it between builds - Add optional answer-first/content-structure linting without making ranking promises - Generate `skill.md`, multiple skill manifests, integrity hashes, and well-known discovery endpoints from project-owned source files - Add schema types appropriate to API references, software applications, organizations, and FAQs only when content qualifies **Exit criteria:** WingTip catches technical discovery regressions before deployment and produces evidence that can be inspected in CI. ### Phase 4 — Reproducible competitive benchmark (P1) Build the same public fixture with WingTip and representative hosted and open-source documentation generators. Record: - Build inputs, product versions, commands, and generated artifacts - HTML availability without client-side JavaScript - Page weight, requests, external origins, and JavaScript execution - Lighthouse and Core Web Vitals lab results under identical conditions - Canonical, robots, sitemap, hreflang, social metadata, structured data, and AI-readable artifacts - Broken-link, accessibility, and schema validation results - Hosting portability and platform-dependent behavior Publish raw outputs and rerunnable automation. Do not claim leadership where the fixture does not prove it. **Exit criteria:** Competitive claims in the README and launch material are generated from public evidence. ### Phase 5 — Workflow and ecosystem (P2) - `wingtip new`, `wingtip check`, and `wingtip migrate` command groups - Browser build-error overlay and improved incremental rebuilds - Preview-deployment recipes for GitHub, Netlify, Cloudflare Pages, and Vercel - PR annotations for audit regressions and visual changes - Theme packages and template overrides - WCAG 2.2 AA audit and regression checks (✅ automated axe-core gate over every generated page in both color schemes, in CI with a negative test, July 17, 2026; expert manual audit still open) - Contributor guide, extension examples, and stable fixtures - Dependency, package-integrity, and generated-CSP checks ### Phase 6 — Optional hosted capabilities (P3) Keep the open-source generator complete on its own. Hosted or partner services may later provide: - Managed builds and previews - Password-protected or authenticated documentation - Team editing and approval workflows - Search/feedback analytics - Edge redirects, headers, and cache controls - Enterprise support and migration services These services must not make existing static generation, SEO metadata, auditing, or output ownership dependent on a WingTip account. ## Success metrics - Migration completion rate and median manual fixes per repository - Percentage of source pages, URLs, redirects, and metadata preserved - Unsupported MDX constructs per migrated repository - Zero unreported data loss - Audit findings caught before production - Generated page weight and external-origin count - Build time across small, medium, and large fixtures - Number of independent deployments that do not use WingTip-managed infrastructure - Search impressions, indexed pages, and AI referrals measured by adopters who opt to share results ## Explicit non-goals - Guaranteed rankings, rich results, or AI citations - A proprietary content repository - Mandatory cloud hosting - Recreating every collaborative editor feature before migration quality is excellent - Generating large volumes of low-quality programmatic content --- File: docs/search-features.md --- # Client-Side Search Functionality WingTip includes a powerful and lightweight client-side search feature that allows users to quickly find relevant information within the documentation. ## How it Works The search functionality is designed to be fast and entirely client-side, making it suitable for static hosting environments like GitHub Pages. Here's a brief overview: 1. **Search Index (`search_index.json`)**: When the site is built, WingTip generates a file named `search_index.json`. This file contains a structured list of all the pages in your documentation (excluding special pages like 404). For each page, the index stores: * The page title. * The plain text content of the page (with HTML tags and frontmatter removed). * The relative URL to the page. 2. **Client-Side Processing**: When a user types into the search bar: * The browser fetches the `search_index.json` file (this happens only once, on the first search interaction typically). * JavaScript running in the browser then filters this index based on the search query. * It matches the query against both the titles and the text content of the pages. * Matching results are displayed dynamically below the search bar as a list of links. ## Using the Search Bar - The search bar is located in the main navigation header for easy access. - Simply type your search terms into the input field. - Results will appear as you type (minimum 2 characters required). - Use keyboard navigation: - Press `/` to focus the search bar - Use `↑` and `↓` arrows to navigate results - Press `Enter` to go to the selected result - Press `Esc` to clear the search - Clicking on a search result will take you directly to the relevant page. - Search results highlight matching text for better visibility. ## Benefits - **Fast**: Since the search happens in the user's browser with a local index, it's very responsive. - **No Server-Side Dependencies**: Works perfectly on static hosting platforms. - **Comprehensive**: Searches both page titles and full text content. - **Accessible**: Full keyboard navigation and screen reader support. - **User-Friendly**: Results highlight matches and update in real-time. This approach ensures that your documentation remains easy to navigate and user-friendly without requiring complex backend infrastructure. --- File: docs/theming.md --- # Theming in WingTip WingTip provides a flexible way to customize the appearance of your documentation site. You can start with basic overrides for fonts and colors, and for more advanced needs, standard CSS practices can be employed. ## Basic Theme Overrides (`theme.json`) The primary way to customize your site's look and feel is by creating a `theme.json` file in the root of your project (the same directory as your `config.json`). This file allows you to define global font choices and specify colors for both light and dark modes. If `theme.json` is not present, or if specific keys within it are missing, WingTip will use its default styles, which are based on Water.css and predefined font stacks. ### Structure of `theme.json` The `theme.json` file has three main top-level keys: * `"fonts"`: For defining global font families. * `"light_mode"`: For defining colors specific to the light theme. * `"dark_mode"`: For defining colors specific to the dark theme. ### Example `theme.json` ```json { "fonts": { "sans_serif": "\"Inter\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, Cantarell, \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\", sans-serif", "monospace": "\"JetBrains Mono\", Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace" }, "light_mode": { "background_body": "#FCFCFC", "background_element": "#FFFFFF", "text_main": "#333333", "text_bright": "#000000", "links_or_primary": "#005FB8", "border": "#E0E0E0" }, "dark_mode": { "background_body": "#1E1E1E", "background_element": "#2C2C2C", "text_main": "#E0E0E0", "text_bright": "#FFFFFF", "links_or_primary": "#3391FF", "border": "#4A4A4A" } } ``` ### Detailed Configuration #### 1. Fonts The `fonts` object accepts two keys: * **`sans_serif`**: (String) A CSS `font-family` stack for the main body text. * _Default_: `system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 'Segoe UI Emoji', 'Apple Color Emoji', 'Noto Color Emoji', sans-serif` * _Example_: `"Inter", sans-serif` * **`monospace`**: (String) A CSS `font-family` stack for code blocks (``) and inline code (``).
* _Default_: `Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace`
* _Example_: `"Fira Code", monospace`
WingTip will use these values to set the `--theme-font-family-sans-serif` and `--theme-font-family-monospace` CSS variables. The `body` and code elements are styled to use these variables.
#### 2. Light Mode & Dark Mode Colors
The `light_mode` and `dark_mode` objects accept the same set of keys to define colors for their respective themes. All values should be valid CSS color strings (e.g., hex codes like `#RRGGBB`, color names like `blue`, `rgb(...)`, `hsl(...)`).
| Key | Corresponding Water.css Variable | Description |
| -------------------- | -------------------------------- | ---------------------------------------------------------------------------------------- |
| `background_body` | `--background-body` | The main background color of the page. |
| `background_element` | `--background` | Background for elements like inline code, inputs, default buttons, even-numbered table rows. |
| `text_main` | `--text-main` | The primary color for most body text. |
| `text_bright` | `--text-bright` | Color for headings (``-``) and bold/strong text. |
| `links_or_primary` | `--links` | Color for hyperlinks. This often serves as the site's primary accent color. |
| `border` | `--border` | Color for table borders, `
` elements, fieldset borders, etc. |
_You can also add other keys if you wish to define additional theme-specific color variables (e.g., `"secondary_accent": "#value"`), which would generate `--theme-color-secondary-accent-light` and `--theme-color-secondary-accent-dark`. These would then need to be used in your own custom CSS._
When you define these color keys, WingTip generates CSS variables that override the default Water.css styles. For example, `light_mode.background_body = "#FAF7F0"` will set the `--background-body` CSS variable to `#FAF7F0` when the light theme is active.
This system allows for quick and easy visual customization of your documentation.
### Tips for Choosing Colors and Fonts
* **Contrast:** Ensure sufficient contrast between text colors and background colors for readability, especially for accessibility (WCAG AA guidelines are a good reference).
* **Font Legibility:** Choose fonts that are clear and easy to read for body text and code. Consider fonts designed for UIs or reading.
* **Consistency:** Try to maintain a consistent feel between your light and dark mode themes, even if colors are inverted.
* **Test:** Always preview your changes in both light and dark modes to ensure they look as expected. Use tools like [Color Contrast Analyzer](https://webaim.org/resources/contrastchecker/) to check contrast ratios.
## Advanced CSS Customization
While `theme.json` provides a straightforward way to change common visual elements, you might have more specific styling needs. For these scenarios, you can:
1. **Create a `custom.css` file:** Place this file in your `static/css/` directory (e.g., `static/css/custom.css`).
2. **Link it in `template.html`:** You would need to modify your local `template.html` (if you've ejected or copied it for customization) to include a link to this stylesheet. Make sure to link it *after* the Water.css link and after the injected theme variables style block if you want your custom CSS to override them.
```html
...
...
```
*(Note: Use a relative path like `./static/css/custom.css` if your site is not served from the root of a domain.)*