sourcey

sourcey

Static HTML documentation derived directly from your specs. Multiple spec formats, one pipeline, no browser runtime.

Documentation that can drift from the spec is fiction. The README says the field is optional; the OpenAPI spec says it is required. The blog post promises a method that the SDK removed two minor versions ago. The Doxygen output cites a parameter that the C++ refactor renamed last week. Every docs system that maintains a parallel artifact to the source of truth will eventually lie.

Sourcey takes the specs themselves as the documentation. OpenAPI, MCP server snapshots, Doxygen XML, Go modules, and rich markdown guides flow into a single normalised representation; the renderer turns that representation into static HTML, the search index, and the llms.txt context files. The output is static HTML and nothing runs in the browser at page-load time. Deploy anywhere static files are served.

The config is TypeScript:

import { defineConfig } from "sourcey";

export default defineConfig({
  name: "Cheese Store",
  theme: {
    preset: "default",         // "default", "minimal", or "api-first"
    colors: { primary: "#f59e0b" },
    fonts: { sans: "'Lexend', sans-serif" },
  },
  navigation: {
    tabs: [
      {
        tab: "Documentation",
        groups: [
          { group: "Getting Started", pages: ["introduction", "quickstart"] },
          { group: "Guides", pages: ["concepts", "webhooks"] },
        ],
      },
      {
        tab: "API Reference",
        openapi: "./openapi.yaml",
      },
      {
        tab: "MCP Server",
        mcp: "./mcp.json",
      },
    ],
  },
});

The config is fully typed with dynamic values and imports. defineConfig() gives you autocomplete and validation before you even run a build.

The pipeline

Most documentation tools parse a spec and render it in one pass. Sourcey treats spec processing as a pipeline with distinct stages:

  OpenAPI   -->  LoadedSpec --> ParsedSpec --> OpenAPI 3.x --> NormalizedSpec --> HTML
  MCP JSON  -->  McpSpec    --------------------------------> NormalizedSpec --> HTML
  Doxygen   -->  DoxygenXML --------------------------------> NormalizedSpec --> HTML
  Go module -->  GodocData  --------------------------------> NormalizedSpec --> HTML
  Markdown  --------------------------------------------------> HTML

  Each path converges at NormalizedSpec: a format-agnostic internal representation
  that the renderer, search indexer, and llms.txt generator all consume.

The loader accepts file paths, URLs, JSON, or YAML. The parser dereferences all $ref pointers. The converter handles Swagger 2.0 by converting to OpenAPI 3.0. The normaliser transforms raw specs into a format-agnostic internal representation; MCP, Doxygen, and godoc have their own normalisers that produce the same output structure. The renderer turns everything into HTML, and each stage is independently testable and replaceable.

Dereferencing happens before conversion, deliberately. $ref pointers need to resolve against the original file’s directory structure. A relative reference like ./schemas.yaml#/Pet only makes sense from the source file’s location, so the resolver runs while that location is still known.

MCP server documentation

Sourcey renders MCP servers as first-class reference documentation. Point it at an mcp.json snapshot (output from mcp-parser) and it generates browsable docs with the same design language as your REST API reference. Tools get purple method pills, resources get green, prompts get blue. Annotation badges surface hints like read-only, destructive, and idempotent at a glance. Connection config cards show developers exactly how to wire the server into Claude, Cursor, or any MCP client; copy the JSON and go.

Code samples generate automatically in JSON-RPC, TypeScript SDK, and Python SDK. Tool calls include arguments, resource reads include URI templates, prompt invocations include parameters. The same pipeline that handles OpenAPI normalisation handles MCP; downstream rendering, search, navigation, and theming all work without special cases.

Theming

Everything visual lives under theme. Colors, fonts, layout dimensions, and a preset that controls the page structure.

Three presets ship out of the box. Default gives you sidebar navigation with a right-side table of contents for prose and sticky code panels for API reference. Minimal strips the sidebar entirely; single centred column, clean for landing pages and changelogs. Api-first is the Stripe layout: sidebar, content, and persistent example panels that appear at a smaller breakpoint so the code is always visible alongside the docs.

The preset controls structure. Colors, fonts, and layout dimensions apply on top of any preset. For anything the config does not cover, theme.css takes an array of CSS file paths loaded after the theme; full override capability without forking.

theme: {
  preset: "api-first",
  colors: { primary: "#3b82f6", light: "#60a5fa", dark: "#2563eb" },
  fonts: { sans: "'Inter', sans-serif", mono: "'Fira Code', monospace" },
  layout: { sidebar: "16rem", content: "48rem" },
  css: ["./brand.css"],
}

Markdown components

Guides support rich components in standard markdown:

<Steps>
  <Step title="Install">Run `npm install sourcey`</Step>
  <Step title="Configure">Create `sourcey.config.ts`</Step>
  <Step title="Build">Run `sourcey build`</Step>
</Steps>

<CardGroup cols={2}>
  <Card title="API Reference" icon="book" href="/api">Full endpoint docs</Card>
  <Card title="Guides" icon="map" href="/docs">Step-by-step tutorials</Card>
</CardGroup>

<AccordionGroup>
  <Accordion title="How does auth work?">We use API keys and OAuth2.</Accordion>
</AccordionGroup>

Dev server

Vite-powered SSR hot reload. Edit a component, a style, your spec, or your markdown; changes appear instantly.

Code samples

Auto-generated at build time. OpenAPI gets ten languages: cURL, JavaScript, TypeScript, Python, Go, Ruby, Java, PHP, Rust, and C#. MCP gets JSON-RPC, TypeScript SDK, and Python SDK. Configurable via codeSamples in sourcey.config.ts; defaults to cURL, JavaScript, and Python for REST, and all three for MCP.

The generator recurses through schemas with cycle detection: example then default then first enum then const then type-specific fallback. String formats produce intelligent defaults (date-time gives an ISO timestamp, email gives user@example.com). Each language gets its own icon in the switcher dropdown (Simple Icons, CC0), and the entire UI is baked into the HTML at build time with no client-side overhead.

Context exports

Every sourcey build generates llms.txt and llms-full.txt alongside your HTML. They are compact and full-text views of the same documentation graph that powers the site: OpenAPI endpoints, MCP tools, resources, prompts, labels, and descriptions. The documentation graph is the core artifact; these files are alternate views for developers, models, or retrieval systems that are pointed at the docs explicitly.

Client-side interactivity

All interactivity is vanilla JavaScript: six small modules concatenated in dependency order. No bundler, no framework.

  • Search: / or Ctrl+K opens a search dialog that filters endpoints and models instantly. Results navigate with arrow keys and Enter.
  • Dark mode: toggle that respects system preference and persists via localStorage. The entire theme switches, not just the code panel.
  • Synced language tabs: switch from curl to Python in one example and every example on the page follows. Selection persists across page loads.
  • Scroll tracking: IntersectionObserver highlights the current section in the sidebar as you scroll.
  • Clipboard copy: one-click copy on code blocks with visual feedback.
  • Sidebar: drawer toggle with close on outside click or Escape.

C++ and Doxygen

Sourcey uses moxygen as a library to consume Doxygen XML directly and produce modern, searchable, themeable documentation. Add a doxygen tab to your sourcey.config.ts, point it at your XML output directory, and your C++ API reference renders natively alongside your markdown guides.

{
  tab: "API Reference",
  doxygen: { xml: "./doxygen/xml", language: "cpp" },
}

Keep your Doxyfile. Keep your comment style. The existing Doxygen toolchain stays in place and Sourcey just renders the output. icey’s own C++ docs run through this pipeline.

Go and godoc

Sourcey extracts Go package documentation natively from your source. No Doxygen detour. Add a godoc tab to your sourcey.config.ts, point it at a Go module, and Sourcey runs go list plus go/parser plus go/doc against the host toolchain to produce consts, vars, functions, types (struct, interface, alias, defined), fields with tags, methods, and examples extracted from *_test.go.

{
  tab: "Go API",
  godoc: { module: ".", packages: ["./..."] },
}

Live mode runs the Go toolchain at build time. Snapshot mode reads a committed godoc.json (generated by sourcey godoc --out godoc.json) so docs hosts without Go installed can still render Go reference. Both modes produce the same pages, the same search index entries, and the same llms.txt content.

For Go-only consumers without a JavaScript toolchain, sourcey-godoc ships as a separate native binary on Homebrew, Scoop, and go install. Generate static Go docs sites or portable JSON snapshots from the same engine, no Sourcey npm package required.

Open source

Sourcey is AGPL-3.0. Free to use, self-host, and modify. If you run it as a hosted service, you open-source your stack. Documentation is infrastructure; it should be owned, not rented.