# Sourcey Sourcey tells the whole product story. Specs, code, rich guides, changelog, roadmap pages, examples, and portable context files from your project as static HTML. ## Documentation ### Introduction Path: `/docs/introduction` Sourcey tells the whole product story. Specs, code, rich guides, changelog, roadmap pages, examples, and portable context files from your project as static HTML. Sourcey builds a static docs site from the source of your product: specs, code, rich guides, changelog, roadmap pages, examples, and portable context files. One config file, one build command. Developers get the browser site. Retrieval systems and model workflows can use llms.txt and llms-full.txt when they are pointed at the docs explicitly. The project keeps the source. Most documentation tools are either hosted platforms that own your content, or bloated frameworks that ship megabytes of JavaScript to render a paragraph. Sourcey does neither. It reads your specs, code, and markdown, then writes HTML files to a directory. The output is yours. Put it on GitHub Pages, Cloudflare Pages, Netlify, S3, your own server. No account required, no vendor to migrate away from later. What you get API Reference Point sourcey at an OpenAPI 3.2, 3.1, or 3.0 spec (or Swagger 2.0; it converts automatically). QUERY operations, hierarchical tags, response summaries, every schema and code sample rendered and searchable. MCP Server Docs Document MCP servers with tools, resources, and prompts rendered as browsable reference. Code samples in JSON-RPC, TypeScript, and Python. Rich Guides Write guides in markdown with frontmatter. Rich components (steps, tabs, cards, callouts) via directive syntax. No JSX imports. Static Output Zero JavaScript framework shipped to the browser. The output is plain HTML, one CSS file, and a small script for search and dark mode. Deploy it anywhere. How it works You create a sourcey.config.ts that declares your tabs, groups, and pages. Markdown files sit alongside it. An OpenAPI spec can be a local file or a URL. Copy sourcey build Copy Sourcey - building documentation site Pages: 14 Output: dist Time: 1.2s The dist/ directory contains your complete documentation site. Serve it with any static file server. Get started in 60 seconds Copy npx sourcey init npm install npx sourcey dev init is interactive; it prompts for a project name, picks a theme preset, and auto-detects any OpenAPI specs or Doxyfiles in your directory. It creates your config, example pages, and package.json. See the Quick Start for the full walkthrough. Tip Already have an OpenAPI spec? Skip the config entirely: sourcey build api.yaml generates a complete API reference from a single file. See it in action The Cheese Store demo is a full sourcey site with markdown guides, an OpenAPI-generated API reference, an MCP tools tab , five navigation tabs, custom branding, and every component type. The source is on GitHub ; clone it, run sourcey dev , and you have a working reference project to build from. ### Install Path: `/docs/install` Every supported install path for Sourcey. npm, Homebrew, Docker, and Nix for the main CLI. Go, Homebrew, and Scoop for the standalone Go docs generator. Sourcey ships through every channel JavaScript, native, and container ecosystems use. Pick the one your project already lives in. Sourcey CLI The full Sourcey binary that handles OpenAPI, Doxygen, godoc, MCP, and Markdown sources. npm Requires Node 20 or later. Copy npm install -g sourcey sourcey init For one-shot use without a global install: Copy npx sourcey init Homebrew Works on macOS and Linuxbrew. Copy brew tap sourcey/tap brew install sourcey sourcey init The formula installs Sourcey through Node under the hood, so it depends on node . If you already have Node, the npm path is a smaller install. Docker The official sourcey/sourcey image runs every CLI command. The image's WORKDIR is /docs and its ENTRYPOINT is sourcey , so the first argument after the image name becomes the subcommand. Initialize a new project (interactive): Copy docker run --rm -it -v " $PWD ":/docs sourcey/sourcey init Build: Copy docker run --rm -v " $PWD ":/docs sourcey/sourcey build Run the dev server. The container needs --host 0.0.0.0 so the dev server binds outside the loopback interface, and -p 4400:4400 to forward the port to the host: Copy docker run --rm -p 4400:4400 -v " $PWD ":/docs sourcey/sourcey dev --host 0.0.0.0 On Linux, files written by the container are owned by root by default. Pass --user "$(id -u):$(id -g)" to keep them owned by your user. On Windows PowerShell, use ${PWD} instead of "$PWD" . Nix Requires a Nix install with flakes enabled. One-shot run: Copy nix run github:sourcey/sourcey Persistent install: Copy nix profile install github:sourcey/sourcey sourcey init Standalone Go docs generator For Go-only consumers without a JavaScript toolchain, sourcey-godoc ships as a separate native binary. It produces static Go docs sites or portable godoc.json snapshots; no Sourcey npm package required. Go Copy go install github.com/sourcey/sourcey/go/sourcey-godoc/cmd/sourcey-godoc@latest Homebrew Copy brew tap sourcey/tap brew install sourcey-godoc Scoop (Windows) Copy scoop bucket add sourcey https://github.com/sourcey/scoop-bucket scoop install sourcey-godoc Local development To work on Sourcey itself: Copy git clone https://github.com/sourcey/sourcey.git cd sourcey npm install npm run build && npm test ### Quick Start Path: `/docs/quickstart` From zero to a running docs site in under a minute. This guide walks through creating a documentation site with an API reference and markdown pages. You'll have a working site running locally in under a minute. Prerequisites Node.js 20 or later An OpenAPI spec or MCP server snapshot (optional; you can start with markdown-only) Get started Scaffolded (fast) Other install paths Copy npx sourcey init npm install npx sourcey dev The init command is interactive. It prompts for a project name and theme preset, and auto-detects any OpenAPI specs or Doxyfiles in your directory. When it finishes you'll have a sourcey.config.ts , example pages, a package.json with dev/build scripts, and a .gitignore . If you're inside an existing project it suggests a docs/ subdirectory so your docs live alongside your source. Sourcey ships through Homebrew ( brew tap sourcey/tap && brew install sourcey ), Docker ( sourcey/sourcey on Docker Hub), and Nix ( nix run github:sourcey/sourcey ). See Install for command details. The rest of this guide assumes sourcey is on your PATH; substitute your install method's invocation if not. The config Every sourcey project starts with a sourcey.config.ts in the project root. This file declares your site structure: tabs, groups, and which pages belong where. If you used init , this was created for you. Copy // sourcey.config.ts import { defineConfig , markdown , openapi } from "sourcey" ; export default defineConfig ({ name: "My Project" , theme: { colors: { primary: "#0066cc" , }, } , navigation: { tabs: [ { tab: "Documentation" , slug: "" , source: markdown ({ groups: [ { group: "Getting Started" , pages: [ "introduction" , "quickstart" ], }, ], }), }, { tab: "API Reference" , slug: "api" , source: openapi ( "./openapi.yaml" ), }, ], } , }) ; Note All file paths in the config are relative to the directory containing sourcey.config.ts . Sourcey looks for this file in your current working directory. Write your first page Create a markdown file for each page referenced in your config. The filename (without extension) must match the slug in the pages array. Copy --- title: Introduction description: Welcome to our documentation. --- This is your first documentation page. Write standard markdown here. ## Features - OpenAPI reference generation - Markdown guides with rich components - Client-side search - Dark mode Start the dev server Copy npx sourcey dev This starts a Vite-powered dev server on port 4400 with hot reload. Edit your markdown or config and the page updates instantly. Build for production Copy npx sourcey build This writes static HTML to dist/ . Every page is a standalone HTML file with inlined styles. No framework runtime ships to the browser. Copy Sourcey - building documentation site Pages: 4 Output: dist Time: 0.8s Deploy the dist/ directory to GitHub Pages, Vercel, Netlify, S3, or any static file host. Tip Already have an OpenAPI spec? Skip the config entirely: sourcey build api.yaml generates a complete API reference from a single file. Next steps Project Structure How sourcey resolves pages, specs, and output. Components Rich directives for steps, tabs, cards, callouts, and more. Cheese Store Demo A complete reference project with multi-tab navigation, OpenAPI integration, and every component type. Clone it and run sourcey dev . ### Project Structure Path: `/docs/project-structure` How sourcey finds your config, markdown files, and OpenAPI specs. A sourcey project is a directory containing a sourcey.config.ts and your content files. There's no required folder hierarchy; sourcey resolves everything relative to the config file. Typical layout Copy my-docs/ sourcey.config.ts # site config (required) introduction.md # markdown pages quickstart.md concepts.md guides/ authentication.md webhooks.md openapi.yaml # OpenAPI spec (optional) logo.png # logo image (optional) dist/ # build output (generated) Config resolution Sourcey looks for sourcey.config.ts in the current working directory when you run sourcey build or sourcey dev . All paths in the config are resolved relative to this file. Copy // These are relative to the directory containing sourcey.config.ts source : openapi ( "./specs/api.yaml" ), logo : "./assets/logo.png" , Page resolution Pages are referenced by slug in the config. Sourcey looks for a .md or .mdx file matching that slug in the config directory. Copy source : markdown ({ groups: [ { group: "Getting Started" , pages: [ "introduction" , "quickstart" ], // Resolves to: introduction.md, quickstart.md }, ], }); Info Glob patterns are supported. "guides/*" expands to all .md and .mdx files in the guides/ directory, sorted alphabetically. Warning Page slugs must be unique across all groups within a tab. Duplicate slugs cause a build error. Output structure After running sourcey build , the output directory contains standalone HTML files, a CSS file, a JavaScript file for client-side search and dark mode, and a search index. Copy dist/ index.html # first page introduction.html quickstart.html concepts.html guides/ authentication.html webhooks.html api.html # API reference (if openapi tab configured) sourcey.css sourcey.js search-index.json Every HTML file is self-contained. No framework runtime, no module loading, no hydration step. ### Writing Pages Path: `/docs/writing-pages` Markdown files with frontmatter. Title, description, and content. Every documentation page is a markdown file with YAML frontmatter. Sourcey handles the rest: syntax highlighting, heading anchors, table of contents, and responsive layout. Frontmatter Each page starts with a YAML block between --- markers. Copy --- title: Getting Started description: Install and configure your first project. --- Page content starts here. Field Required Purpose title Yes Page heading, sidebar label, and search result title description No SEO meta description and search result snippet Tip Write descriptive titles and descriptions. They appear in the sidebar navigation and in search results; good metadata makes your docs navigable at a glance. Headings Standard markdown headings work as expected. Sourcey extracts h2 and h3 headings for the table of contents sidebar. Copy ## Section Heading (appears in TOC) ### Subsection Heading (also appears in TOC) #### Deeper headings (not in TOC, still rendered) If your first heading is an h1 that matches the title in frontmatter, sourcey strips it to avoid duplication. The title from frontmatter is always rendered as the page heading. Code blocks Fenced code blocks get syntax highlighting via Shiki. Specify the language after the opening backticks. Copy ```typescript const config = defineConfig({ name: "My Docs", }); ``` Shiki supports most languages out of the box: TypeScript, JavaScript, Python, Go, Rust, Ruby, Java, PHP, C, C++, Bash, JSON, YAML, and many more. Standard markdown All standard markdown features work as expected: Bold and italic text Links (external links open in a new tab) Ordered and unordered lists Tables with standard pipe syntax Inline code and block code Images via ![alt](url) Blockquotes via > Rich components Beyond standard markdown, sourcey supports directives for richer content: callouts, steps, tabs, code groups, cards, and accordions. See the Components page for the full reference. ### Components Path: `/docs/components` Rich components in plain markdown. No JSX, no imports, just directives. Sourcey renders directives in standard markdown. The ::: syntax is processed at build time; no JavaScript ships for static content. Every component on this page is rendered using the syntax it documents. To see all of these components used in a real project, check the Cheese Store demo and its source on GitHub . Callouts Four types for different contexts. Add text after the type to override the default title. Note Use note for supplementary information that supports the surrounding content. Warning Use warning for things that will break, cost money, or lose data if ignored. Tip Use tip for shortcuts, best practices, or non-obvious techniques. Info Use info for context that helps the reader understand why something works the way it does. Custom Title Add text after the type to set a custom title. This callout uses :::note Custom Title . Syntax: Copy :::note Content here. ::: :::warning Custom Title Content with a custom title. ::: Available types: note , warning , tip , info . Steps Numbered processes with a visual connector line. Write a standard ordered list inside :::steps . 1 Write the directive Open with :::steps on its own line. 2 Add numbered items Use a standard markdown ordered list. The first line is the step title; subsequent indented lines are the content. 3 Close it End with ::: on its own line. Syntax: Copy :::steps 1. Step title Step content goes here. Indent by 3 spaces. 2. Another step More content. ::: Tabs Tabbed content panels. Each tab is a ::tab child with a title attribute. First Tab Second Tab Third Tab Content for the first tab. This tab is active by default. Content for the second tab. Click to reveal. Tabs work for any content: text, code blocks, lists, images. Syntax: Copy :::tabs ::tab{title="Tab Name"} Content here. :: ::tab{title="Another Tab"} More content. :: ::: Code Group Tabbed code blocks with syntax highlighting. Wrap fenced code blocks in :::code-group . Each block needs a title attribute. Node.js Python cURL Copy const res = await fetch ( 'https://api.example.com/items' ); const data = await res . json (); Copy import requests res = requests.get( 'https://api.example.com/items' ) data = res.json() Copy curl -s 'https://api.example.com/items' | jq Syntax: Copy :::code-group ```javascript title="Node.js" const res = await fetch('https://api.example.com/items'); ``` ```python title="Python" import requests res = requests.get('https://api.example.com/items') ``` ::: Cards Grid of linked or static cards with icons. Wrap ::card children in :::card-group . The cols attribute controls the grid (2, 3, or 4 columns on desktop; always 1 on mobile). With a link Cards with an href attribute are clickable and navigate to that page. With an icon Cards without href are static. Use them to highlight features or concepts. Minimal Only title is required. Icon and href are optional. Two-column variant: Left card Two-column layouts work well for binary choices or before/after comparisons. Right card The grid is responsive. On mobile, cards always stack vertically. Syntax: Copy :::card-group{cols="3"} ::card{title="Card Title" icon="book-open" href="/path"} Card content. :: ::card{title="Another Card" icon="lock-closed"} More content. :: ::: Attributes: card-group : cols (number of columns, default 2) card : title (required), icon (optional), href (optional) Accordion Expandable sections using the HTML element. Consecutive accordions are automatically grouped. Is this rendered with details/summary? Yes. Each accordion is a native element with a styled . No JavaScript required for the expand/collapse behavior. Do consecutive accordions group automatically? They do. Place multiple :::accordion blocks one after another and sourcey wraps them in a visual group with shared borders. Can I have a single accordion? Absolutely. A single :::accordion renders standalone without group styling. Syntax: Copy :::accordion{title="Question or section title"} Answer or content here. ::: Place multiple accordions consecutively for automatic grouping. Video Embed YouTube, Vimeo, or raw video files. YouTube URLs are rewritten to youtube-nocookie.com for privacy. Syntax: Copy ::video[https://www.youtube.com/watch?v=VIDEO_ID]{title="Optional title"} ::video[https://vimeo.com/123456789]{title="Vimeo video"} ::video[https://example.com/video.mp4]{title="Self-hosted video"} YouTube and Vimeo URLs render as iframes. Raw .mp4 and .webm URLs render as native elements. Iframe Embed any external page. Only https:// and http:// URLs are allowed. Syntax: Copy ::iframe[https://example.com]{title="Example embed" height="400"} Attributes: title (optional): accessible label for the iframe height (optional, default 400 ): height in pixels JSX syntax Sourcey also accepts JSX-style component syntax. These are preprocessed to directives internally, so the output is identical. Copy Content Content Content Content (fenced code blocks with title attributes) Content Answer Informational callout Warning with custom title Helpful suggestion Contextual information Info Directive syntax ( ::: ) is the recommended format. JSX syntax exists for compatibility and convenience; both produce the same HTML output. Warning Nesting directives inside other directives is not supported. Each directive block must be a top-level element in your markdown. ### OpenAPI Integration Path: `/docs/openapi-integration` Point sourcey at a spec. Get a complete API reference with code samples. Tip Documenting an MCP server instead? See MCP Integration . Sourcey generates API reference documentation from OpenAPI specs. Every operation, parameter, response, and schema is rendered with auto-generated code samples in up to 10 languages. Supported formats Format Support OpenAPI 3.2 Native (including QUERY operations, response summaries, hierarchical tags, deviceAuthorization OAuth, querystring parameters, media-type encoding, $self -aware refs) OpenAPI 3.1 Native OpenAPI 3.0 Native Swagger 2.0 Auto-converted to OpenAPI 3.x at build time YAML Yes JSON Yes URL Yes (fetched at build time) Configuration Add an openapi() source tab to your config. The path is relative to sourcey.config.ts . Copy import { defineConfig , openapi } from "sourcey" ; export default defineConfig ({ navigation: { tabs: [ { tab: "API Reference" , slug: "api" , source: openapi ( "./openapi.yaml" ), }, ], } , }) ; For a quick build from a standalone spec (no config file needed): Copy sourcey build ./openapi.yaml What gets generated Each tagged group of operations becomes a section in the sidebar. For every operation, sourcey renders: HTTP method and path Description and summary Parameters (path, query, header, cookie) with types and constraints Request body schema with examples Response schemas for each status code Auto-generated code samples Code samples Sourcey auto-generates request examples from your spec in up to 10 languages. The default set is curl , javascript , and python . Configure the full list with codeSamples in your config. See the Code Samples reference for all available languages and options. Copy codeSamples : [ "curl" , "javascript" , "typescript" , "python" , "go" ], Spec validation Sourcey validates your spec at build time. Invalid specs fail the build with actionable error messages. You can also validate without building: Copy sourcey validate ./openapi.yaml Copy Valid: My API v1.0.0 Operations: 24 Schemas: 12 Note Validation parses, dereferences, and normalizes the spec. It catches structural issues, missing references, and invalid schema definitions before they break your documentation. See sourcey validate for full details. ### MCP Integration Path: `/docs/mcp-integration` Document MCP servers with tools, resources, and prompts rendered as browsable reference docs. Sourcey generates reference documentation from Model Context Protocol server snapshots. Tools, resources, resource templates, and prompts render with the same quality as OpenAPI specs: parameter tables, expandable schemas, code samples, and search. Note MCP support was added in Sourcey 3.4.0. Make sure you're on the latest version. Configuration Add an mcp() source tab to your config. The path points to an mcp.json file relative to sourcey.config.ts . Copy import { defineConfig , mcp } from "sourcey" ; export default defineConfig ({ navigation: { tabs: [ { tab: "MCP Reference" , slug: "mcp" , source: mcp ( "./mcp.json" ), }, ], } , }) ; MCP tabs work alongside any other tab type. A typical setup pairs an MCP reference with markdown guides: Copy import { defineConfig , markdown , mcp } from "sourcey" ; export default defineConfig ({ navigation: { tabs: [ { tab: "MCP Reference" , slug: "mcp" , source: mcp ( "./mcp.json" ), }, { tab: "Guides" , source: markdown ({ groups: [ { group: "Getting Started" , pages: [ "introduction" , "quickstart" ] }, ], }), }, ], } , }) ; What is mcp.json? An mcp.json file is a static snapshot of an MCP server's capabilities. It captures the tools, resources, and prompts that an MCP server exposes at runtime, in a versionable JSON file. You can generate one from a running server with mcp-parser , or write it by hand. The format mirrors the MCP protocol's own introspection responses. See the MCP ecosystem page for the full type definitions and tooling. What gets rendered Tools Each tool renders as an operation card with: A purple TOOL method pill and the tool name Description Parameter table from the tool's inputSchema properties, each marked as "argument" Expandable schema view for tools with nested or complex input structures Returns section showing the outputSchema (or a default MCP content array description) Auto-generated code samples in JSON-RPC, TypeScript SDK, and Python SDK Resources and resource templates Resources render with a green RESOURCE pill and the resource URI. Resource templates (like weather://{city}/forecast ) extract path parameters from the URI template and display them in a parameter table. Prompts Prompts render with a blue PROMPT pill and the prompt name. Arguments are listed as parameters. Sidebar The sidebar groups operations by type: Tools , Resources , Prompts . Each group only appears if the spec contains that type. You can override grouping with the x-sourcey-group vendor extension on any tool, resource, or prompt. Code samples Every operation gets auto-generated code samples in three formats: Copy { "jsonrpc" : "2.0" , "method" : "tools/call" , "params" : { "name" : "get_weather" , "arguments" : { "city" : "San Francisco" } } } Copy const result = await client . callTool ( "get_weather" , { city: "San Francisco" , }); Copy result = await session.call_tool( "get_weather" , arguments = { "city" : "San Francisco" , }) Connection config If the spec includes transport information, a connection config card renders below the introduction showing how to add the server to an MCP client: Copy { "mcpServers" : { "my-server" : { "command" : "npx" , "args" : [ "my-mcp-server" ] } } } The card also shows the MCP protocol version, transport type, and declared capabilities. Annotation badges Tools with annotations display coloured badges: Annotation Badge readOnlyHint read-only (green) destructiveHint destructive (red) idempotentHint idempotent (blue) openWorldHint open-world (amber) Live example The Cheese Store MCP tab demonstrates MCP rendering with tools, resources, resource templates, and prompts. Next steps Generate mcp.json from a running server using mcp-parser Tutorial: document your MCP server step by step mcp-schema and mcp-parser ecosystem packages ### Themes & Layout Path: `/docs/themes-and-layout` Three presets, custom colors, fonts, layout dimensions, and CSS overrides. Sourcey ships with three layout presets. Each preset defines the page structure; colors, fonts, and dimensions are customizable on top of any preset. Presets default minimal api-first Sidebar navigation on the left, content in the center, table of contents on the right. The standard layout for documentation sites with many pages. Copy theme : { preset : "default" , // this is the default; you can omit it } Single-column layout with no sidebar or table of contents. Content is centered and reads like a document. Good for single-page docs or READMEs. Copy theme : { preset : "minimal" , } Three-column layout inspired by Stripe's API docs. Sidebar on the left, documentation in the center, code samples pinned to the right. Best for API-heavy sites. Copy theme : { preset : "api-first" , } Colors Three color values control the theme. Only primary is required; light and dark default to the primary value if not set. Copy theme : { colors : { primary : "#0066cc" , // links, active states, accent elements light : "#3399ff" , // hover states, lighter accents dark : "#003d99" , // active/pressed states }, } Colors must be 6-digit hex values. Sourcey converts them to RGB for use in CSS custom properties. Fonts Override the default font stacks for sans-serif and monospace text. Copy theme : { fonts : { sans : "Inter" , // body text, headings mono : "JetBrains Mono" , // code blocks, inline code }, } Defaults: sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif mono: 'Geist Mono', 'SF Mono', 'Fira Code', 'Cascadia Code', Consolas, monospace Tip Sourcey automatically loads custom fonts from Google Fonts. Set the font name in your config and it handles the tag and preconnect hints. Layout dimensions Control the width of the sidebar, table of contents, and content area. Values are CSS length strings. Copy theme : { layout : { sidebar : "18rem" , // default: "18rem" toc : "19rem" , // default: "19rem" content : "44rem" , // default: "44rem" }, } Custom CSS Inject additional CSS files that load after the default theme. Paths are relative to sourcey.config.ts . Copy theme : { css : [ "./custom.css" ], } This is the escape hatch for styling that the config doesn't cover. Sourcey's HTML uses semantic class names, so you can target any element reliably. For the full type definitions and default values, see the Theme Tokens reference . For a step-by-step branding walkthrough, see Custom Branding . ### Dark Mode Path: `/docs/dark-mode` Built in. localStorage persistence. Light and dark logo variants. Dark mode works out of the box with zero configuration. A toggle appears in the navbar. The user's preference persists in localStorage across sessions and pages. How it works Sourcey applies a .dark class to the root element when dark mode is active. All built-in components and syntax highlighting themes respond to this class. The toggle state is read from localStorage on page load before the first paint, so there's no flash of the wrong theme. Logo variants If your logo doesn't work on both light and dark backgrounds, provide separate variants: Copy logo : { light : "./logo.png" , // shown in light mode dark : "./logo-dark.png" , // shown in dark mode href : "/" , // optional: where the logo links to }, A single string still works if your logo handles both modes: Copy logo : "./logo.png" , Custom CSS in dark mode If you're using custom CSS , target dark mode with the .dark selector on the root element: Copy /* custom.css */ .dark .my-custom-element { background : #1a1a2e ; color : #e0e0e0 ; } Info Dark mode requires no configuration. It works with every preset and every color scheme. All built-in theme colors generate appropriate dark variants automatically. ### Search Path: `/docs/search` Client-side fuzzy search. Cmd+K. Works offline. Sourcey builds a search index at build time and ships it as a static JSON file. Search runs entirely in the browser with no external service. How it works During sourcey build , every page is indexed: titles, descriptions, headings, and body content. For OpenAPI tabs, operation summaries, paths, methods, and parameter names are also indexed. The result is a search-index.json file in the output directory. At runtime, Cmd+K (or Ctrl+K on Linux/Windows) opens the search dialog. Results update as you type using fuzzy matching. Arrow keys navigate results, Enter selects. What gets indexed Source Indexed fields Markdown pages title, description, h2/h3 headings, body text OpenAPI operations summary, description, HTTP method, path, operation ID OpenAPI schemas schema name, description Note Search requires no configuration and no external service. It works offline once the page is loaded, which makes it suitable for air-gapped or self-hosted deployments. ### Deploying Path: `/docs/deploying` Static HTML. Deploy to GitHub Pages, Vercel, Netlify, S3, or anywhere. sourcey build writes static HTML to a directory. No server, no runtime, no build step on the hosting side. Upload the files and you're done. Copy sourcey build -o dist Hosting options GitHub Pages Push the output directory to a gh-pages branch or configure GitHub Actions to build and deploy. Free for public repos. Netlify Drop the output directory into a Netlify site. Set the build command to npx sourcey build and the publish directory to dist . Vercel Same approach as Netlify. Build command: npx sourcey build . Output directory: dist . S3 / CloudFront Upload the output to an S3 bucket with static website hosting enabled. Add CloudFront for HTTPS and caching. GitHub Actions The sourcey/build-docs action handles the build step for you: Copy name : Deploy Docs on : push : branches : [ main ] jobs : deploy : runs-on : ubuntu-latest steps : - uses : actions/checkout@v4 - uses : sourcey/build-docs@v1 with : output : dist - uses : peaceiris/actions-gh-pages@v4 with : github_token : ${{ secrets.GITHUB_TOKEN }} publish_dir : ./dist Or install manually if you prefer more control: GitHub Actions (manual) Netlify (netlify.toml) Vercel (vercel.json) Copy name : Deploy Docs on : push : branches : [ main ] jobs : deploy : runs-on : ubuntu-latest steps : - uses : actions/checkout@v4 - uses : actions/setup-node@v4 with : node-version : 20 - run : npm install - run : npx sourcey build -o dist - uses : peaceiris/actions-gh-pages@v4 with : github_token : ${{ secrets.GITHUB_TOKEN }} publish_dir : ./dist Copy [build] command = "npx sourcey build" publish = "dist" Copy { "buildCommand" : "npx sourcey build" , "outputDirectory" : "dist" } Clean URLs By default, sourcey emits foo.html and links carry the .html suffix. Set prettyUrls in sourcey.config.ts to strip the extension: Copy export default defineConfig ({ prettyUrls: "slash" , // "/foo/" - works on any static host // or prettyUrls: "strip" , // "/foo" - needs extensionless HTML support navigation: { tabs: [ /* ... */ ] } , }) ; "slash" writes each page as foo/index.html , which every static host serves at /foo/ automatically. "strip" writes each page as foo.html and links to /foo ; use it on hosts that serve extensionless HTML paths. Host Notes Cloudflare Pages serves foo.html at /foo , so prettyUrls: "strip" is a good fit. Vercel supports the same public URL style with cleanUrls: true : Copy { "buildCommand" : "npx sourcey build" , "outputDirectory" : "dist" , "cleanUrls" : true } For simple static hosts that do not serve foo.html at /foo , use prettyUrls: "slash" instead. Sitemap Every build generates a sitemap.xml in the output directory. Submit it to Google Search Console or add it to your robots.txt : Copy Sitemap: https://docs.example.com/sitemap.xml Subfolder deployment To serve docs under a path like /docs/ on an existing site, build the output into that subfolder of your static directory: Copy sourcey build -o ./public/docs The output is self-contained with relative asset paths. It works in any subdirectory without configuration changes. Embeddable output The --embed flag produces HTML without the , , and wrappers. This is useful for embedding sourcey output in an iframe or injecting it into an existing page. Copy sourcey build --embed -o ./embed Tip Committing built output to your repo is a valid deployment strategy. It means zero build step on the hosting side and guarantees the deployed site matches what you reviewed locally. For a detailed walkthrough of embedding docs in an existing site, see the Embedding guide . For all build flags, see sourcey build . ### Changelog Path: `/docs/changelog` All notable changes to Sourcey. Format based on [Keep a Changelog](https://keepachangelog.com/). #### 3.6.0 (2026-05-15) - Added: Source adapters as the primary tab configuration shape: source: markdown(...) , mkdocs(...) , openapi(...) , mcp(...) , doxygen(...) , and godoc(...) . - Added: mkdocs() source adapter for importing existing mkdocs.yml / mkdocs.yaml sites. Sourcey reads docs_dir , nav , and legacy pages , preserves explicit page labels, flattens nested MkDocs sections into Sourcey sidebar groups, expands snippets, normalizes admonitions/tabs, and carries static assets into the build. - Changed: sourcey init , first-party docs, examples, and 0state docs configs now use the adapter form. Legacy direct tab fields remain supported for existing projects. #### 3.5.10 (2026-05-10) - Fixed: Desktop sidebar scroll position now survives sidebar-initiated page navigation, so long generated docs sidebars no longer jump back to the top after selecting deep items in Doxygen/moxygen, OpenAPI, MCP, godoc, Markdown, or changelog tabs. - Fixed: Direct, search-result, and external deep links now reveal the active sidebar item without reusing stale sidebar state. #### 3.5.9 (2026-05-06) - Added: Native Go documentation as a fifth tab source ( godoc ). Sourcey extracts package docs directly from Go source via the toolchain ( go list + go/parser + go/doc ); no Doxygen pipeline. Supports live mode (runs Go at build time) and snapshot mode (reads a committed godoc.json ); mode: "auto" (default) picks live when Go is available and snapshot otherwise. Renders consts, vars, functions, types (struct, interface, alias, defined), fields with tags, methods, and examples from *_test.go . - Added: sourcey godoc --module . --packages './...' --out godoc.json CLI command to snapshot a Go module's documentation into a portable JSON artifact for JS-only docs hosts. - Added: Standalone sourcey-godoc Go module and CLI at github.com/sourcey/sourcey/go/sourcey-godoc/cmd/sourcey-godoc , with generate for static Go docs sites, snapshot for portable JSON, and cross-platform GitHub release binaries on go/sourcey-godoc/v* tags. - Added: goEnv option ( GOOS / GOARCH / tags ) for pinning the live-mode Go build environment so docs reproduce across hosts. - Added: includeTests , includeUnexported , hideUndocumented , and exclude options on godoc tabs. - Added: godoc package and symbol entries flow through the existing search index, llms.txt , llms-full.txt , and sitemap.xml pipelines. - Changed: Changelog page descriptions now render inline markdown so links and inline code resolve, with a constrained reading width and primary-tinted underlined links. - Changed: Unreleased version cards drop the dashed border for a primary-tinted left accent and soft tint, with a "Next release" pill in place of the empty meta row. - Fixed: Changelog parser no longer leaks bullet/paragraph tokens from non-SemVer headings into the page description, so trailing historical sections stop polluting the lead paragraph. #### 3.5.8 (2026-05-06) - Added: sourcey dev --host <address> flag (and HOST env var fallback) to control the Vite dev-server bind address. Defaults to 127.0.0.1 . Use --host 0.0.0.0 (or -e HOST=0.0.0.0 in Docker) to expose the dev server outside the host so the official sourcey/sourcey image's dev command works end-to-end. #### 3.5.6 (2026-05-05) - Fixed: Output-relative .html links between generated pages now resolve through the active prettyUrls mode, cleaning Doxygen body links such as icy.html#anchor when prettyUrls: "strip" is enabled. #### 3.5.5 (2026-05-05) - Fixed: Generated Doxygen page descriptions now render as plain text, preventing stale .html cross-reference links from appearing in page headers and metadata when prettyUrls: "strip" is enabled. #### 3.5.4 (2026-05-05) - Fixed: Generated Godoc and Doxygen tab navigation now normalizes through the active prettyUrls mode, so prettyUrls: "strip" builds do not emit stale .html or index.html navigation links. #### 3.5.3 (2026-05-05) - Fixed: prettyUrls: "strip" now emits foo.html files and public /foo links, without generated _redirects , so extensionless hosts do not loop between slashless and trailing-slash paths. - Fixed: Internal markdown links that still point at .html pages are rewritten to the active pretty URL form when they resolve to a generated page. #### 3.5.1 (2026-05-04) - Fixed: Sidebar nav and OpenAPI tab anchor base now honour prettyUrls ("slash" / "strip"). Previously hrefs were hard-coded to slug.html / tab/index.html , which 404 on hosts that don't auto-rewrite (e.g. GitHub Pages). Production sourcey.com masked the issue with its /foo.html → /foo/ 308 redirect. #### 3.5.0 (2026-04-24) - Added: OpenAPI 3.2 parsing and rendering for QUERY operations, response summaries, deviceAuthorization OAuth flows, hierarchical tags, querystring parameters, and media-type encoding metadata - Added: $self -aware reference resolution for canonical multi-document OpenAPI descriptions - Added: prettyUrls config option for clean URLs ( "slash" emits foo/index.html and links as /foo/ ; "strip" links as /foo and emits a _redirects file for static hosts that support redirect rules) - Changed: OG image template redesigned for legibility at Slack/Discord preview sizes: larger bold wordmark, vertical accent bar in theme primary, tighter type, single-grey description, no duplicate site-name footer - Fixed: Lint configuration for browser-side client scripts and generated MCP test artifacts #### 3.4.12 (2026-04-16) - Added: Automatic per-page OG image generation at build time using Satori and resvg - Added: ogImage config option for overriding with a static image URL - Added: Heroicons in navigation and UI components - Changed: Inter loaded as the default sans-serif; layout rhythm refined for tighter vertical spacing - Fixed: Tab path deduplication when multiple tabs share a slug - Fixed: Inline code styling inside TOC items - Fixed: TOC nested-item border alignment #### 3.4.5 (2026-04-07) - Added: Nested directives (e.g. tabs inside :::code-group ) - Added: Doxygen link rewriting for cross-referenced symbols in prose - Fixed: Inline code protection during markdown directive preprocessing #### 3.4.4 (2026-04-06) - Fixed: OAuth security section rendering - Fixed: Footer logo restored after layout refactor - Fixed: Fenced markdown examples preserved through directive preprocessing #### 3.4.3 (2026-04-05) - Added: ::iframe directive for embedding arbitrary https URLs in markdown - Fixed: Doxygen page summaries now reuse resolved cross-links in page headers instead of exposing raw {#ref ... #} placeholders - Fixed: Rich Doxygen index cards strip inline markdown link syntax from summaries - Fixed: sourcey init now scaffolds projects against the latest published version again - Fixed: Minimal-theme callout borders and responsive page description sizing - Fixed: TOC sub-item margin alignment - Fixed: Search featured pages, inline dialog, display font, and sidebar dot markers - Fixed: Lighthouse baseline polish for generated docs #### 3.4.0 (2026-04-02) - Added: MCP server documentation as a first-class input format alongside OpenAPI, Markdown, and Doxygen - Added: mcp tab config option for rendering tools, resources, and prompts from an mcp.json snapshot - Added: Auto-generated code samples in JSON-RPC, TypeScript SDK, and Python SDK for all MCP operations - Added: Connection config card showing how to add the server to Claude, Cursor, or any MCP client - Added: Annotation badges for tool hints (read-only, destructive, idempotent, open-world) - Added: Colour-coded sidebar method pills (purple TOOL, green RES, blue PRMT) - Added: Hot-reload for mcp.json files in the dev server - Added: ::video directive for embedding YouTube, Vimeo, or raw video files in markdown - Added: Sitemap generation - Added: OpenGraph and Twitter Card meta tags - Added: Dockerfile for Docker Hub - Added: Nix flake support - Changed: Sidebar active state uses pill-style background instead of left border - Changed: Table of contents uses a continuous grey track with primary colour active marker - Changed: Clicking the first sidebar item scrolls to the top of the page - Fixed: Dev server fs.allow now includes the sourcey root for npm link compatibility - Fixed: Double-wrapped accordion groups from <AccordionGroup> component syntax #### 3.3.10 (2026-03-30) - Changed: Package metadata moved to sourcey.com and sourcey/sourcey org - Fixed: Node 24 JSON import compatibility #### 3.3.9 (2026-03-28) - Fixed: Page slugs preserve directory structure to avoid nav collisions #### 3.3.8 (2026-03-28) - Fixed: slugFromPath preserves directory structure #### 3.3.7 (2026-03-27) - Added: Relative source links in markdown rewrite to repo URLs at build time #### 3.3.6 (2026-03-27) - Added: Doxygen index page generation - Fixed: Doxygen index content links #### 3.3.5 (2026-03-26) - Fixed: CLI help output reports the actual package version - Fixed: sourcey init scaffolds new projects with the latest published version #### 3.3.4 (2026-03-26) - Changed: First page renders directly instead of meta-refresh redirect #### 3.3.2 (2026-03-25) - Added: sourcey init auto-detects project type and offers directory selection - Added: Init reads Doxygen XML_OUTPUT for proper path resolution #### 3.3.1 (2026-03-25) - Fixed: Use jiti for TypeScript config loading - Fixed: Resolve moxygen from npm registry #### 3.3.0 (2026-03-25) - Added: sourcey init command for scaffolding new projects - Added: Scroll tracker ?target query parameter for deep linking - Added: Node 24 in CI test matrix #### 3.2.1 (2026-03-24) - Fixed: Dev server asset path resolution for npm installs #### 3.2.0 (2026-03-23) - Added: Internal link resolution between markdown pages - Added: editBasePath config option for repos with docs in a subdirectory - Added: Previous/next page navigation at the bottom of markdown pages - Added: Brand icons (GitHub, npm, etc.) in navbar and footer #### 3.1.0 (2026-03-22) - Added: Mobile navigation drawer with breadcrumbs - Added: Configurable tab slugs - Added: Collapsible schemas in API reference - Added: "Edit this page" links on markdown pages - Added: Auto Google Fonts loading from theme config - Changed: Stone-palette code surfaces - Changed: TOC nesting improvements - Fixed: Responsive layout at small breakpoints - Fixed: Code indent rendering - Fixed: Dev server error recovery - Fixed: Sidebar active state on prose pages - Fixed: Duplicate h1 headings - Fixed: Logo paths resolve relative to config directory #### 3.0.2 (2026-03-21) - Added: Geist Mono as default monospace font - Changed: Config changes hot-reload in dev server - Fixed: Scroll offset calculation #### 3.0.1 (2026-03-21) - Added: Doxygen C++ documentation via Moxygen integration - Added: Command palette search (Cmd+K) - Added: Google Fonts loading and font stack configuration - Fixed: Moxygen resolved from npm registry - Fixed: TOC scroll tracking - Fixed: Heading scroll offset #### 3.0.0 (2026-03-20) - Added: Redesigned theme with new layout, typography, and colour system - Added: Theme presets (default, minimal, api-first) with custom colours, fonts, and layout - Added: EndpointBar component with colour-coded method badges - Added: CopyButton and SocialIcon UI components - Added: Demo site with markdown guides - Added: Unified Vite plugin for dev server - Changed: Renamed from spectacle-docs to sourcey - Changed: License changed from MIT to AGPL-3.0-only - Changed: Complete redesign of Header, Sidebar, Page, TableOfContents, CodeSamples, Responses, and Security components - Removed: Legacy Handlebars/Foundation/SCSS theme - Removed: TabBar and old CodeBlock components #### 2.1.0 (2026-03-19) - Added: Multi-page sites with tabbed navigation and sidebar groups - Added: Markdown pages with rich components (Steps, Cards, Accordions) - Added: Vite dev server with SSR hot reload - Added: Header with navbar links and CTA button - Added: Table of contents with scroll tracking - Added: Footer with social links - Added: Cross-page navigation link resolution - Changed: Dark example panel hidden on prose-only pages #### 2.0.2 (2026-03-19) - Added: Vite dev server with header, TOC, and layout system #### 2.0.0 (2026-03-10) Complete rewrite from Handlebars/Grunt to TypeScript/Preact SSG. - Added: TypeScript codebase with Preact SSR - Added: sourcey.config.ts with defineConfig() and full type safety - Added: OpenAPI 3.x support (auto-converts Swagger 2.0) - Added: Shiki syntax highlighting - Added: Dark mode with localStorage persistence - Added: Client-side search with keyboard navigation (Cmd+K) - Added: Auto-generated code samples in 10 languages - Added: Custom colour theming with hex-to-RGB token system - Added: Stone-palette code blocks with language dropdown and response tabs - Added: Copy button on code blocks - Added: Scroll-tracked sidebar navigation - Added: Enum pills and array item type display - Added: Logo support with light/dark variants - Added: Static HTML output with no framework runtime - Added: GitHub Actions CI - Removed: Handlebars template engine - Removed: Grunt build system - Removed: highlight.js #### 1.1.0 (2020-03-10) - Fixed: Example rendering - Fixed: Dependency vulnerabilities (handlebars, js-yaml, lodash, marked, fstream) #### 1.0.7 (2019-01-30) - Added: YAML example support - Fixed: Href with colon characters - Fixed: Href with multiple dots - Fixed: Code block overflow #### 1.0.6 (2018-09-20) - Changed: Licence update #### 1.0.5 (2018-07-02) - Changed: Updated Grunt dependencies #### 1.0.4 (2018-07-01) - Fixed: grunt-sass 3.0 compatibility - Fixed: grunt-sass dependency resolution #### 1.0.3 (2018-04-15) - Added: Nested objects and arrays in definitions - Added: Resource embedding support - Added: Enum definition descriptions - Added: $ref support in parameters and responses - Added: Development mode with live reload - Added: Schema syntax error reporting in dev mode - Added: x-nullable support #### 1.0.2 (2018-03-22) - Changed: Security partial rendering #### 1.0.1 (2018-03-21) - Fixed: Markdown rendering (#122, #126) - Fixed: Schema description rendering and linking #### 1.0.0 (2018-03-20) First stable release. Requires Node.js >= 8. - Added: Quiet output option - Fixed: Remote file reference rendering #### 0.9.12 (2017-11-13) - Added: Response header display - Fixed: Null node error in reference resolution #### 0.9.11 (2017-10-13) - Fixed: Null check in reference replacement #### 0.9.10 (2017-09-27) - Fixed: Remote reference tests #### 0.9.9 (2017-09-27) - Added: Min/max range display for parameters - Added: maxLength and minLength display for strings - Added: Better rendering of arrays of objects #### 0.9.8 (2017-09-01) - Fixed: Rendering on large screens with indents #### 0.7.0 (2017-02-01) - Added: Programmatic API with promise return #### 0.6.9 (2017-01-16) - Added: Remote schema support - Added: Temporary directory per build run #### 0.6.8 (2017-01-13) - Fixed: Code highlighting - Fixed: HTTPS for jQuery reference #### 0.5.0 (2016-12-31) - Added: OpenAPI 2.0 (Swagger) rendering - Added: Foundation 6 responsive layout with drawer navigation - Added: Custom logo support - Added: Docker support - Added: Recursive example parsing - Added: Definition rendering with JSON examples - Added: Custom CSS scoping - Added: Handlebars template engine ## Guides ### Your First Docs Site Path: `/docs/guides/guide-first-docs-site` Build a complete documentation site from scratch. API reference plus markdown guides. This tutorial builds a documentation site for a fictional "Tasks API" with markdown guides and an auto-generated API reference. By the end, you'll have a multi-tab site with navigation, search, and dark mode. What we're building A docs site with two tabs: Documentation - an introduction page and a quickstart guide API Reference - auto-generated from an OpenAPI spec Note This tutorial takes about 15 minutes. If you just want to see the minimal setup, the Quick Start page covers the essentials in under 5 minutes. Setup 1 Create the project directory Copy mkdir tasks-docs && cd tasks-docs npm init -y npm install sourcey 2 Create the config Create sourcey.config.ts in the project root: Copy import { defineConfig , markdown , openapi } from "sourcey" ; export default defineConfig ({ name: "Tasks API" , theme: { colors: { primary: "#6366f1" , }, } , navigation: { tabs: [ { tab: "Documentation" , slug: "" , source: markdown ({ groups: [ { group: "Getting Started" , pages: [ "introduction" , "quickstart" ], }, ], }), }, { tab: "API Reference" , slug: "api" , source: openapi ( "./openapi.yaml" ), }, ], } , navbar: { links: [ { type: "github" , href: "https://github.com/your-org/tasks-api" }, ], } , }) ; 3 Write the introduction page Create introduction.md : Copy --- title: Introduction description: The Tasks API lets you create, manage, and track tasks programmatically. --- The Tasks API is a REST API for task management. Authenticate with an API key, make requests, get JSON responses. ## Features :::card-group{cols="2"} ::card{title="Task Management" icon="book-open"} Create, update, delete, and list tasks. Assign priorities, due dates, and labels. :: ::card{title="Webhooks" icon="bell"} Get notified when tasks are created, completed, or overdue. :: ::: 4 Write the quickstart page Create quickstart.md : Copy --- title: Quick Start description: Make your first API request in under a minute. --- :::steps 1. Get an API key Sign up at the dashboard and copy your API key. 2. Create a task ```bash curl -X POST https://api.tasks.dev/v1/tasks \ -H "Authorization: Bearer YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"title": "Ship the docs", "priority": "high"}' ``` 3. Verify it worked ```bash curl https://api.tasks.dev/v1/tasks \ -H "Authorization: Bearer YOUR_KEY" ``` ::: 5 Add an OpenAPI spec Create openapi.yaml with your API spec. If you don't have one yet, you can use any valid OpenAPI 3.x file to test the setup. 6 Start the dev server Copy npx sourcey dev Open http://localhost:4400 . You should see your docs with sidebar navigation, a table of contents, and working search. 7 Build for production Copy npx sourcey build The dist/ directory contains your complete site. Deploy it anywhere. What to do next Add more pages by creating markdown files and referencing them in the config Customize the theme with your brand colors and logo Set up repo and editBranch in the config to enable "Edit this page" links Configure codeSamples to control which languages appear in the API reference Tip Want a more complete reference? The Cheese Store demo is a production-quality sourcey project with four tabs, markdown guides, an OpenAPI-generated API reference, custom branding, and every component type. Clone it and use it as a starting point: git clone https://github.com/cheesestore/docs && cd docs && npm install && npx sourcey dev . ### Custom Branding Path: `/docs/guides/guide-custom-branding` Your colors, your fonts, your logo. Make it yours. Sourcey defaults to a clean indigo theme. This guide walks through replacing it with your own brand identity. For the full reference of all theme options, see Themes & Layout and Theme Tokens . Start with colors The fastest way to make sourcey feel like your product. Three hex values control the entire color scheme. 1 Set your primary color Copy theme : { colors : { primary : "#0066cc" , }, } This single value drives links, active states, sidebar highlights, and accent elements. The light and dark variants default to the primary if not set. 2 Add light and dark variants Copy theme : { colors : { primary : "#0066cc" , light : "#3399ff" , // hover states, lighter accents dark : "#003d99" , // pressed states, darker accents }, } 3 Rebuild Copy npx sourcey dev Every accent in the site now uses your palette. Add a logo Copy logo : "./assets/logo.png" , If your logo doesn't work on both light and dark backgrounds: Copy logo : { light : "./assets/logo.png" , dark : "./assets/logo-dark.png" , href : "/" , }, Warning Colors must be valid 6-digit hex values. Shorthand like #f00 won't work; use #ff0000 . Change fonts Override the sans-serif and monospace font stacks: Copy theme : { fonts : { sans : "Inter" , mono : "JetBrains Mono" , }, } Sourcey automatically loads custom fonts from Google Fonts. Just set the name: Copy theme : { fonts : { sans : "Inter" , mono : "JetBrains Mono" , }, } Sourcey generates the Google Fonts tag and preconnect hints at build time. If your font isn't on Google Fonts, load it via a custom CSS file instead: Copy theme : { fonts : { sans : "My Custom Font" }, css : [ "./fonts.css" ], } Add a favicon Copy favicon : "./assets/favicon.png" , Custom CSS overrides For anything the config doesn't cover, inject a CSS file: Copy theme : { css : [ "./custom.css" ], } Sourcey's HTML uses semantic class names ( .sidebar , .toc , .page-content , .callout , etc.) so you can target any element reliably. The custom CSS loads after the default theme, so your rules take precedence. Full example Copy import { defineConfig } from "sourcey" ; export default defineConfig ({ name: "Acme Docs" , theme: { colors: { primary: "#0066cc" , light: "#3399ff" , dark: "#003d99" , }, fonts: { sans: "Inter" , mono: "JetBrains Mono" , }, css: [ "./brand.css" ], } , logo: { light: "./assets/logo.png" , dark: "./assets/logo-dark.png" , href: "/" , } , favicon: "./assets/favicon.png" , navigation: { tabs: [ /* ... */ ] } , }) ; ### Multi-Tab Sites Path: `/docs/guides/guide-multi-tab-sites` Combine markdown guides, API reference, and more in a single site. Sourcey supports multiple tabs, each with its own source adapter: markdown groups, MkDocs, an OpenAPI spec, an MCP snapshot, Doxygen XML, or native godoc data. Tabs appear in the top navigation and define independent URL namespaces. Tab types Each tab has exactly one content source: Source Adapter Use case Markdown groups markdown({ groups }) Guides, tutorials, concepts, changelogs MkDocs mkdocs("./mkdocs.yml") Import an existing MkDocs site OpenAPI spec openapi("./openapi.yaml") Auto-generated API reference MCP snapshot mcp("./mcp.json") MCP server tools, resources, and prompts Doxygen XML doxygen({ xml }) C/C++ API reference Go packages godoc(".") Go package and symbol reference Example: five-tab site Copy import { defineConfig , godoc , markdown , openapi } from "sourcey" ; export default defineConfig ({ name: "My Platform" , navigation: { tabs: [ { tab: "Documentation" , slug: "" , source: markdown ({ groups: [ { group: "Getting Started" , pages: [ "introduction" , "quickstart" ], }, { group: "Concepts" , pages: [ "architecture" , "authentication" ], }, ], }), }, { tab: "Guides" , source: markdown ({ groups: [ { group: "Tutorials" , pages: [ "guide-setup" , "guide-deployment" ], }, ], }), }, { tab: "API Reference" , slug: "api" , source: openapi ( "./openapi.yaml" ), }, { tab: "Go API" , slug: "go-api" , source: godoc ({ module: "." , packages: [ "./..." ], }), }, { tab: "Changelog" , source: markdown ({ groups: [ { group: "Updates" , pages: [ "changelog" ], }, ], }), }, ], } , }) ; How slugs work Each tab has a URL slug. Pages within a tab are prefixed with that slug. Root slug (empty string) Named slug Custom slug Copy { tab : "Documentation" , slug : "" } Pages live at the root: /introduction , /quickstart . Use this for your primary tab to keep URLs short. Copy { tab : "Guides" , slug : "guides" } Pages are prefixed: /guides/guide-setup , /guides/guide-deployment . When slug is omitted, it defaults to the slugified tab name. Copy { tab : "API Reference" , slug : "api" } Override the auto-generated slug for cleaner URLs: /api/ instead of /api-reference/ . Tip Set slug: "" on your primary documentation tab. This puts the most-visited pages at the shortest URLs. Groups within tabs Groups organize pages in the sidebar. Each group gets a section header. Copy source : markdown ({ groups: [ { group: "Getting Started" , // sidebar section header pages: [ "introduction" , "quickstart" ], }, { group: "Advanced" , pages: [ "architecture" , "performance" ], }, ], }); Pages appear in the sidebar in the order they're listed. Groups appear in the order they're defined. Real-world example The Cheese Store demo uses the same multi-tab pattern for guides and OpenAPI reference. The Scafld Go API is the live godoc reference: a Go API tab generated from package comments and exported symbols. ### Tutorial: Document Your MCP Server Path: `/docs/guides/guide-mcp-docs` Generate browsable documentation from an MCP server in five minutes. This tutorial walks through generating documentation for an MCP server. You'll snapshot a running server, configure sourcey, and build a complete reference site. Prerequisites Node.js 20 or later A running MCP server (or you can hand-write an mcp.json ) 1. Snapshot your server Install mcp-parser and snapshot your running server: Copy npx mcp-parser snapshot --stdio "node my-server.js" -o mcp.json For servers that use SSE or streamable HTTP: Copy npx mcp-parser snapshot --sse http://localhost:3000/sse -o mcp.json npx mcp-parser snapshot --http http://localhost:3000/mcp -o mcp.json This creates an mcp.json file capturing your server's tools, resources, and prompts. You can also write mcp.json by hand if you prefer. 2. Validate the snapshot Copy npx mcp-parser validate ./mcp.json Copy Valid: no issues found. 3. Create a sourcey project Copy npm install sourcey Create sourcey.config.ts : Copy import { defineConfig , mcp } from "sourcey" ; export default defineConfig ({ name: "My MCP Server" , navigation: { tabs: [ { tab: "MCP Reference" , slug: "" , source: mcp ( "./mcp.json" ), }, ], } , }) ; 4. Preview locally Copy npx sourcey dev Open http://localhost:4400 . You should see your tools in the sidebar with purple method pills, resources in green, and prompts in blue. 5. Add markdown guides Create an introduction.md alongside your config: Copy --- title: Introduction description: Getting started with the MCP server. --- Your server description and usage instructions here. Add a guides tab to your config: Copy import { defineConfig , markdown , mcp } from "sourcey" ; export default defineConfig ({ navigation: { tabs: [ { tab: "MCP Reference" , slug: "mcp" , source: mcp ( "./mcp.json" ), }, { tab: "Guides" , slug: "" , source: markdown ({ groups: [{ group: "Getting Started" , pages: [ "introduction" ] }], }), }, ], } , }) ; 6. Build and deploy Copy npx sourcey build The dist/ directory contains your complete site. The build also emits llms.txt and llms-full.txt as portable context views of the same documentation graph. Deploy the output to any static host: GitHub Pages, Netlify, Vercel, S3, or your own server. Example The Cheese Store MCP tab is a working example with tools, resources, resource templates, and prompts. See the source on GitHub for the config and mcp.json. ### Go / godoc Docs Path: `/docs/guides/guide-godoc-go` Generate Go API reference from package comments, exported symbols, and examples. Sourcey can render Go package documentation directly from Go source. Use a godoc tab when your project has package comments, exported functions, types, methods, fields, constants, variables, or examples that should live beside your guides and API docs. The live reference is the Scafld Go API: 0state.com/scafld/docs/go-api . When to use it Use native godoc support when: your Go API reference currently only lives on pkg.go.dev ; you want package docs inside your own documentation site; you want Go symbols included in Sourcey search, llms.txt , and llms-full.txt ; you need guides, changelog, OpenAPI, MCP, Doxygen, and Go reference in one static site. Do not route Go through Doxygen. Go source, doc comments, examples, module metadata, and the Go toolchain are the source of truth. Configure a Go API tab Copy import { defineConfig , godoc , markdown } from "sourcey" ; export default defineConfig ({ name: "My Go Project" , navigation: { tabs: [ { tab: "Documentation" , slug: "" , source: markdown ({ groups: [ { group: "Getting Started" , pages: [ "introduction" , "quickstart" ] }, ], }), }, { tab: "Go API" , slug: "go-api" , source: godoc ({ module: "." , packages: [ "./..." ], includeTests: true , }), }, ], } , }) ; module points at the Go module root. packages uses the same pattern shape as go list , so ./... includes every package below the module root. String shorthand For the common case, pass the module path directly: Copy { tab : "Go API" , source : godoc ( "." ), } This expands to a live build over ./... with examples enabled. Snapshot mode If the docs build host does not have Go installed, generate a portable snapshot and commit it: Copy npx sourcey godoc --module . --packages './...' --out docs/godoc.json Then configure Sourcey to read the snapshot: Copy { tab : "Go API" , slug : "go-api" , source : godoc ({ snapshot: "./godoc.json" , mode: "snapshot" , }), } Snapshot mode is useful for static docs hosts, hermetic CI jobs, and repos that want deterministic docs output across machines. Standalone Go CLI Go-only teams can use sourcey-godoc without installing Node: Copy go install github.com/sourcey/sourcey/go/sourcey-godoc/cmd/sourcey-godoc@latest sourcey-godoc generate --out site The standalone CLI is the small Go-first path. The full Sourcey site is the path when you want Go reference beside guides, specs, changelog, examples, and agent-readable output. Output Sourcey renders: one module overview page; one page per selected package; package docs from // Package ... comments; exported constants, variables, functions, types, methods, and fields; examples from _test.go files when includeTests is enabled; stable symbol anchors; entries in search, sitemap, llms.txt , and llms-full.txt . The result is still static HTML. No runtime service is required. ### Doxygen / C++ Docs Path: `/docs/guides/guide-doxygen-cpp` Generate API reference from Doxygen XML output. Sourcey can generate documentation from Doxygen XML output, making it possible to document C and C++ libraries alongside markdown guides in a single site. Prerequisites Doxygen installed and configured to output XML Your Doxygen XML output directory (usually xml/ inside the Doxygen output directory) Setup 1 Generate Doxygen XML Ensure your Doxyfile has XML output enabled: Copy GENERATE_XML = YES XML_OUTPUT = xml Run Doxygen: Copy doxygen Doxyfile 2 Configure a Doxygen tab Add a tab with a doxygen() source pointing to your XML output directory: Copy import { defineConfig , doxygen , markdown } from "sourcey" ; export default defineConfig ({ name: "My C++ Library" , navigation: { tabs: [ { tab: "Documentation" , slug: "" , source: markdown ({ groups: [{ group: "Getting Started" , pages: [ "introduction" ] }], }), }, { tab: "C++ API" , slug: "cpp-api" , source: doxygen ({ xml: "./doxygen-output/xml" , }), }, ], } , }) ; 3 Build Copy npx sourcey build The C++ API tab renders classes, functions, enums, and type definitions from the Doxygen output. Configuration options Copy source : doxygen ({ xml: "./path/to/xml" , // path to Doxygen XML directory (required) language: "cpp" , // language hint (default: "cpp") groups: false , // use Doxygen @defgroup for navigation (default: false) }); How it works Sourcey uses Moxygen internally to parse Doxygen's XML output into structured documentation. Moxygen is bundled as a dependency; you don't need to install it separately. It extracts classes, functions, enums, typedefs, and their documentation comments from the XML, and sourcey renders them using the same layout, styling, and search indexing as all other pages. When groups is set to true , sourcey uses Doxygen's @defgroup / @ingroup annotations to organize the sidebar navigation. When false (the default), it organizes by file and namespace. ### Embedding in Existing Sites Path: `/docs/guides/guide-embedding` Add sourcey docs as a subfolder in your existing website. Sourcey's output is static HTML that can be dropped into any existing website's public directory. This is how sourcey.com itself works: these docs are built with sourcey and served from /docs/ alongside the Astro marketing site. Subfolder deployment Build the output directly into your site's public directory: Copy sourcey build -o ./public/docs Your existing site framework (Astro, Next.js, Hugo, plain Nginx) serves the public/ directory as static files. The sourcey output at /docs/ is completely self-contained: its own CSS, its own JS, its own search index. No conflicts with your main site's styles or scripts. Build script integration Add a build script to your package.json : Copy { "scripts" : { "build:docs" : "cd docs && npx sourcey build -o ../public/docs" } } This assumes your sourcey config and markdown live in a docs/ subdirectory. Adjust paths to match your project layout. Embeddable output For iframe embedding, use the --embed flag. This strips the , , and wrappers, producing bare content suitable for injection into an existing page. Copy sourcey build --embed -o ./embed Warning Embedded output expects its CSS and JS files to be served from the same directory. Make sure the output directory is accessible at the path the iframe src points to. Real-world example This documentation site is itself built with sourcey. The setup: A docs/ directory in the sourcey.com repo contains sourcey.config.ts and all markdown files npm run build:docs runs sourcey build -o ../public/docs The Astro site serves public/docs/ as static files at /docs/ The "Docs" link in the navbar points to /docs/ The marketing site and the documentation site are independently built and independently styled. They share a URL but nothing else. ### Build Ask AI with Sourcey and LangChain Path: `/docs/guides/guide-langchain-retriever` Implement your own Ask AI feature over a Sourcey docs site. If you want an Ask AI feature over your docs, this is the thin layer. Sourcey already ships the files a retriever needs: search-index.json llms-full.txt stable page URLs That means you do not need a hosted index just to make your docs usable from LangChain. Publish the docs site. Point the retriever at it. Done. Install Python: Copy pip install -U langchain-sourcey JavaScript: Copy npm install langchain-sourcey @langchain/core What it reads Both langchain-sourcey packages work against a published Sourcey docs root. It uses: search-index.json to find candidate pages llms-full.txt to hydrate full page content the page URL as the LangChain citation source If llms-full.txt is missing, it falls back to the matched page HTML. Quickstart Python: Copy from langchain_sourcey import SourceyRetriever retriever = SourceyRetriever( site_url = "https://sourcey.com/docs" , top_k = 3 , ) docs = retriever.invoke( "mcp integration" ) for doc in docs: print (doc.metadata[ "title" ]) print (doc.metadata[ "source" ]) print (doc.page_content[: 160 ]) print () site_url should be the root of a published Sourcey build: https://sourcey.com/docs https://sourcey.com/cheesestore https://cheesestore.github.io JavaScript: Copy import { SourceyRetriever } from "langchain-sourcey" ; const retriever = new SourceyRetriever ({ siteUrl: "https://sourcey.com/docs" , topK: 3 , }); const docs = await retriever . invoke ( "mcp integration" ); for ( const doc of docs ) { console . log ( doc . metadata . title ); console . log ( doc . metadata . source ); console . log ( doc . pageContent . slice ( 0 , 160 )); console . log (); } Implement Ask AI Install a chat model package. This example uses OpenAI. Python: Copy pip install -U langchain-openai Copy from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate from langchain_core.runnables import RunnablePassthrough from langchain_openai import ChatOpenAI from langchain_sourcey import SourceyRetriever retriever = SourceyRetriever( site_url = "https://sourcey.com/docs" , top_k = 3 ) prompt = ChatPromptTemplate.from_template( """Answer the question using the documentation context below. {context} Question: {question} """ ) chain = ( RunnablePassthrough.assign( context = ( lambda x : x[ "question" ]) | retriever) | prompt | ChatOpenAI( model = "gpt-4.1-mini" ) | StrOutputParser() ) print (chain.invoke({ "question" : "How does Sourcey document MCP servers?" })) JavaScript: Copy npm install @langchain/openai Copy import type { Document } from "@langchain/core/documents" ; import { StringOutputParser } from "@langchain/core/output_parsers" ; import { ChatPromptTemplate } from "@langchain/core/prompts" ; import { RunnablePassthrough , RunnableSequence } from "@langchain/core/runnables" ; import { ChatOpenAI } from "@langchain/openai" ; import { SourceyRetriever } from "langchain-sourcey" ; const retriever = new SourceyRetriever ({ siteUrl: "https://sourcey.com/docs" , topK: 3 , }); const prompt = ChatPromptTemplate . fromTemplate ( `Answer the question using the documentation context below. {context} Question: {question}` ); const formatDocs = ( docs : Document []) => docs . map (( doc ) => doc . pageContent ). join ( " \n\n " ); const chain = RunnableSequence . from ([ { context: retriever . pipe ( formatDocs ), question: new RunnablePassthrough (), }, prompt , new ChatOpenAI ({ model: "gpt-4.1-mini" }), new StringOutputParser (), ]); console . log ( await chain . invoke ( "How does Sourcey document MCP servers?" )); The contract If you want this to work cleanly on your own docs site, keep these stable: publish search-index.json publish llms-full.txt set siteUrl so page URLs are canonical That is the whole trick. Sourcey emits the retrieval surface as part of the normal docs build, so the LangChain integration stays thin. Package PyPI: langchain-sourcey npm: langchain-sourcey GitHub: sourcey/langchain-sourcey ### Generating mcp.json Path: `/docs/guides/mcp-snapshot` Snapshot a running MCP server or write the spec by hand. An mcp.json file captures an MCP server's tools, resources, and prompts in a static, versionable format. Sourcey reads this file to generate documentation. From a running server mcp-parser connects to an MCP server, calls the introspection endpoints, and writes the snapshot to disk. Copy npm install mcp-parser stdio Copy mcp-parser snapshot --stdio "node my-server.js" -o mcp.json SSE Copy mcp-parser snapshot --sse http://localhost:3000/sse -o mcp.json Streamable HTTP Copy mcp-parser snapshot --http http://localhost:3000/mcp -o mcp.json Authentication Pass headers for servers that require auth: Copy mcp-parser snapshot --http https://api.example.com/mcp \ --header "Authorization:Bearer your-token" \ -o mcp.json By hand You can write mcp.json directly. The format mirrors the MCP protocol's own type definitions. Here's a minimal example: Copy { "mcpSpec" : "0.2.0" , "server" : { "name" : "my-server" , "version" : "1.0.0" }, "description" : "What this server does." , "tools" : [ { "name" : "my_tool" , "description" : "What this tool does." , "inputSchema" : { "type" : "object" , "properties" : { "query" : { "type" : "string" , "description" : "Search query" } }, "required" : [ "query" ] } } ] } See mcp-schema for the full type definitions and JSON Schema. Validating Check an mcp.json for structural errors and best-practice warnings: Copy mcp-parser validate ./mcp.json Copy Valid: no issues found. Validation checks for required fields, duplicate names, missing descriptions, and invalid schemas. Generating docs Generate a markdown reference from the snapshot: Copy mcp-parser generate ./mcp.json -o mcp.md Generate a compact llms.txt -style index for tools that already consume that convention: Copy mcp-parser generate ./mcp.json --format llms-txt -o llms.txt For the full-text context export: Copy mcp-parser generate ./mcp.json --format llms-full-txt -o llms-full.txt Note sourcey build also emits llms.txt and llms-full.txt automatically as part of the site build. The mcp-parser CLI is useful when you want standalone markdown or context files without building a full docs site. ### MCP Ecosystem Path: `/docs/guides/mcp-ecosystem` mcp-schema and mcp-parser, TypeScript tooling for MCP server specifications. Sourcey's MCP support is built on two standalone npm packages published under the sourcey org. They're useful independently of sourcey for any project that works with MCP server specifications. mcp-schema TypeScript types and JSON Schema for the mcp.json snapshot format. Copy npm install mcp-schema Copy import type { McpSpec , McpTool , McpResource } from "mcp-schema" ; import { mcpSpecSchema } from "mcp-schema/schema" ; Provides typed interfaces for the full MCP surface: tools (with inputSchema , outputSchema , annotations), resources, resource templates, prompts, server capabilities, and transport configuration. The JSON Schema can be used with any validator (Ajv, Zod, etc.). Zero runtime dependencies. GitHub npm mcp-parser Snapshot, parse, validate, and document MCP server specifications. Copy npm install mcp-parser Copy import { parse , validate , snapshot , generateMarkdown } from "mcp-parser" ; const spec = await parse ( "./mcp.json" ); const result = validate ( spec ); const markdown = generateMarkdown ( spec ); API Function Description parse(path) Parse an mcp.json file with $ref dereferencing parseString(json) Parse from a JSON string validate(spec) Check for errors and best-practice warnings snapshot(options) Connect to a running server and capture a snapshot generateMarkdown(spec) Generate a full markdown reference generateLlmsTxt(spec) Generate a compact llms.txt-style index generateLlmsFullTxt(spec) Generate a full-text context reference CLI Copy mcp-parser parse ./mcp.json mcp-parser validate ./mcp.json mcp-parser snapshot --stdio "node server.js" -o mcp.json mcp-parser snapshot --sse http://localhost:3000/sse -o mcp.json mcp-parser snapshot --http http://localhost:3000/mcp -o mcp.json mcp-parser generate ./mcp.json -o mcp.md mcp-parser generate ./mcp.json --format llms-txt -o llms.txt Depends on mcp-schema for types. GitHub npm How they fit into sourcey Sourcey depends on mcp-parser (which brings mcp-schema transitively). When you add an mcp tab to your config, sourcey uses mcp-parser to parse the mcp.json file and then normalizes it into the same internal format used for OpenAPI specs. The rendering pipeline, search, navigation, and theming work identically. You don't need to install mcp-parser or mcp-schema separately to use MCP tabs in sourcey. They're included as dependencies. Supported MCP protocol versions Both packages support all released versions of the MCP specification : Protocol Version Status 2025-11-25 Current stable 2025-06-18 Supported 2025-03-26 Supported 2024-11-05 Supported MCP specification resources MCP Specification (current stable) Specification repo TypeScript SDK ( @modelcontextprotocol/sdk ) Python SDK ( mcp on PyPI) ## Configuration ### sourcey.config.ts Path: `/docs/config/ref-config` Full configuration reference. Every option, every type. Sourcey is configured with a TypeScript file that exports a SourceyConfig object via defineConfig() . The only required field is navigation.tabs . Minimal config Copy import { defineConfig , markdown } from "sourcey" ; export default defineConfig ({ navigation: { tabs: [ { tab: "Documentation" , slug: "" , source: markdown ({ groups: [ { group: "Getting Started" , pages: [ "introduction" ], }, ], }), }, ], } , }) ; Full config Copy import { defineConfig } from "sourcey" ; export default defineConfig ({ name: "My Docs" , theme: { preset: "default" , colors: { primary: "#0066cc" , light: "#3399ff" , dark: "#003d99" , }, fonts: { sans: "Inter" , mono: "JetBrains Mono" , }, layout: { sidebar: "18rem" , toc: "19rem" , content: "44rem" , }, css: [ "./custom.css" ], } , logo: { light: "./logo.png" , dark: "./logo-dark.png" , href: "/" , } , favicon: "./favicon.png" , repo: "https://github.com/org/repo" , editBranch: "main" , codeSamples: [ "curl" , "javascript" , "python" ] , navigation: { tabs: [ /* ... */ ], } , navbar: { links: [{ type: "github" , href: "https://github.com/org/repo" }], primary: { type: "button" , label: "Dashboard" , href: "https://app.example.com" , }, } , footer: { links: [{ type: "github" , href: "https://github.com/org/repo" }], } , }) ; For a production example of a complete config, see the Cheese Store demo source . Field reference name Display name for the documentation site. Appears in the header alongside the logo. Type: string Default: "" theme Theme configuration. Controls the visual appearance of the site. Type: ThemeConfig (see Theme Tokens ) Field Type Default Description preset "default" | "minimal" | "api-first" "default" Layout preset colors.primary string "#6366f1" Primary accent color (6-digit hex) colors.light string primary value Lighter accent variant colors.dark string primary value Darker accent variant fonts.sans string Inter system stack Sans-serif font family fonts.mono string Geist Mono system stack Monospace font family layout.sidebar string "18rem" Sidebar width layout.toc string "19rem" Table of contents width layout.content string "44rem" Content area width css string[] [] Custom CSS file paths logo Site logo displayed in the header. Type: string | { light: string; dark?: string; href?: string } As a string, it's a path to a single logo image. As an object, you can provide separate light/dark variants and an optional link target. favicon Path to a favicon file. Type: string repo GitHub repository URL. Enables the repository link in the navbar and powers "Edit this page" links when combined with editBranch . Type: string Example: "https://github.com/org/repo" editBranch Git branch name for "Edit this page" links. When set (along with repo ), each markdown page shows an edit link pointing to the source file on GitHub. Type: string Example: "main" codeSamples Languages for auto-generated API code samples. Applies to OpenAPI tabs. MCP tabs generate JSON-RPC, TypeScript, and Python samples automatically. Type: string[] Default: ["curl", "javascript", "python"] Available: "curl" , "javascript" , "typescript" , "python" , "go" , "ruby" , "java" , "php" , "rust" , "csharp" prettyUrls Clean URL emission mode. By default, pages are written as foo.html and linked with the extension. Enable pretty URLs to choose a slash URL or a true extensionless URL. Type: false | "slash" | "strip" Default: false Value On disk Public URL Host requirement false foo.html /foo.html Any static host "slash" foo/index.html /foo/ Any static host "strip" foo.html /foo Host must serve extensionless HTML Use "slash" when you want pretty URLs that work on any static host. Use "strip" for a clean extensionless cutover: Sourcey writes foo.html , links to /foo , and does not generate compatibility redirects. Choose it only on hosts that serve foo.html for /foo , such as Cloudflare Pages. Copy export default defineConfig ({ prettyUrls: "strip" , navigation: { tabs: [ /* ... */ ], } , }) ; When enabled, the sitemap, canonical tags, search index, internal markdown links, and llms.txt all render the selected public URL form. navigation Site navigation structure. The only required top-level field. Type: { tabs: TabConfig[] } See Navigation for the full tab and group reference. Tab sources include groups , mkdocs , openapi , mcp , doxygen , and godoc . navbar Header navigation links and optional CTA button. Type: { links?: NavbarLink[]; primary?: { type: "button"; label: string; href: string } } See Navbar & Footer for link types. footer Footer navigation links. Type: { links?: NavbarLink[] } Tip Use defineConfig() for TypeScript autocomplete. It's an identity function that returns the config as-is, but gives your editor full type information. ### Theme Tokens Path: `/docs/config/ref-theme-tokens` Colors, fonts, layout dimensions, and CSS overrides. The theme field in sourcey.config.ts controls the visual appearance of your documentation site. Every token has a sensible default; you only need to set what you want to change. ThemeConfig interface Copy interface ThemeConfig { preset ?: "default" | "minimal" | "api-first" ; colors ?: { primary : string ; light ?: string ; dark ?: string ; }; fonts ?: { sans ?: string ; mono ?: string ; }; layout ?: { sidebar ?: string ; toc ?: string ; content ?: string ; }; css ?: string []; } Preset defaults default minimal api-first Sidebar + content + table of contents. The standard documentation layout. Token Value layout.sidebar "18rem" layout.toc "19rem" layout.content "44rem" Single-column, centered content. No sidebar, no table of contents. Token Value layout.sidebar N/A layout.toc N/A layout.content "44rem" Three-column layout with code samples pinned to the right. Token Value layout.sidebar "18rem" layout.toc N/A layout.content "44rem" Color tokens Token Default Usage primary #6366f1 (indigo) Links, active sidebar items, accent borders, focus rings light Same as primary Hover states, lighter accent backgrounds dark Same as primary Pressed/active states, darker accent elements Colors must be 6-digit hex values. Sourcey converts them to space-separated RGB values for CSS custom properties, enabling opacity modifiers. Font stacks Token Default sans 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif mono 'Geist Mono', 'SF Mono', 'Fira Code', 'Cascadia Code', Consolas, monospace When you set a custom font name, sourcey uses it as the first entry in the stack with the system fallbacks appended. CSS overrides The css array accepts paths to CSS files loaded after the default theme: Copy theme : { css : [ "./overrides.css" , "./syntax.css" ], } Paths are relative to sourcey.config.ts . Files are concatenated in order. ### Navigation Path: `/docs/config/ref-navigation` Tabs, groups, pages, and slugs. Navigation is the only required field in sourcey.config.ts . It defines the tab structure, sidebar groups, and page ordering. TabConfig Copy interface TabConfig { tab : string ; // display name (required) slug ?: string ; // URL slug (defaults to slugified tab name) source : SourceAdapter ; // created with markdown(), mkdocs(), openapi(), mcp(), doxygen(), or godoc() } Each tab must have exactly one content source. Sourcey 3.6 uses source: adapter(...) as the primary shape. Legacy direct fields ( groups , mkdocs , openapi , mcp , doxygen , and godoc ) still resolve for existing projects. MkDocs source Use mkdocs when a project already has a mkdocs.yml and you want Sourcey to render the same markdown source without rewriting the navigation by hand. Copy navigation : { tabs : [ { tab: "Documentation" , source: mkdocs ( "./mkdocs.yml" ), }, ], } Sourcey reads docs_dir (default docs ) and imports nav / legacy pages . Top-level MkDocs nav sections become sidebar groups. Nested sections are flattened into labels like Guide / Install ; explicit page labels are preserved. Local .md and .mdx pages are supported. External nav entries are ignored. GroupConfig Copy interface GroupConfig { group : string ; // sidebar section header (required) pages : string []; // page slugs (required) } Pages are listed by slug (filename without extension). Sourcey resolves "quickstart" to quickstart.md or quickstart.mdx in the config directory. Slug resolution Config Generated slug Example URL slug: "" (root) /introduction slug: "guides" guides /guides/webhooks slug: "api" api /api/ slug omitted slugified tab name Tab "API Reference" becomes /api-reference/ Warning Tab slugs must be unique. Page slugs must be unique within a tab. Duplicate slugs cause a build error with a message identifying the collision. Glob patterns Page arrays support trailing glob patterns for automatic file discovery: Copy source : markdown ({ groups: [ { group: "API Guides" , pages: [ "api-*" ], // Matches: api-auth.md, api-errors.md, api-pagination.md }, ], }); Matched files are sorted alphabetically. Use explicit page lists when order matters. Page ordering Pages appear in the sidebar in the order they're listed in the pages array. Groups appear in the order they're defined in the groups array. Tabs appear in the order they're defined in the tabs array. There's no implicit ordering. The config is the source of truth for navigation structure. ### Navbar & Footer Path: `/docs/config/ref-navbar-footer` Links, social icons, and CTA buttons. The navbar and footer display links to external resources (GitHub, npm, social accounts) and an optional call-to-action button. NavbarLink Copy interface NavbarLink { type : LinkType ; href : string ; label ?: string ; } Link types Each type renders with its corresponding icon. The label field is optional and provides accessible text. Type Icon Example "github" GitHub { type: "github", href: "https://github.com/org/repo" } "npm" npm { type: "npm", href: "https://npmjs.com/package/name" } "twitter" X/Twitter { type: "twitter", href: "https://x.com/handle" } "discord" Discord { type: "discord", href: "https://discord.gg/invite" } "linkedin" LinkedIn { type: "linkedin", href: "https://linkedin.com/company/org" } "youtube" YouTube { type: "youtube", href: "https://youtube.com/@channel" } "slack" Slack { type: "slack", href: "https://workspace.slack.com" } "mastodon" Mastodon { type: "mastodon", href: "https://mastodon.social/@user" } "bluesky" Bluesky { type: "bluesky", href: "https://bsky.app/profile/user" } "reddit" Reddit { type: "reddit", href: "https://reddit.com/r/sub" } "link" Generic link { type: "link", href: "https://example.com", label: "Blog" } Primary CTA button The navbar supports a single primary button that appears prominently in the header: Copy navbar : { primary : { type : "button" , label : "Get Started" , href : "https://app.example.com" , }, } Footer The footer uses the same NavbarLink type: Copy footer : { links : [ { type: "github" , href: "https://github.com/org/repo" }, { type: "twitter" , href: "https://x.com/handle" }, ], } Full example Copy navbar : { links : [ { type: "github" , href: "https://github.com/sourcey/sourcey" }, { type: "npm" , href: "https://www.npmjs.com/package/sourcey" }, { type: "discord" , href: "https://discord.gg/sourcey" }, ], primary : { type : "button" , label : "Live Demo" , href : "/cheesestore" , }, }, footer : { links : [ { type: "github" , href: "https://github.com/sourcey/sourcey" }, { type: "twitter" , href: "https://x.com/sourcey" }, ], }, ### Code Samples Path: `/docs/config/ref-code-samples` Auto-generated code samples for API endpoints. Sourcey generates request code samples from your OpenAPI spec. Each operation in the API reference displays tabbed examples showing how to call the endpoint in multiple languages. Configuration Copy codeSamples : [ "curl" , "javascript" , "typescript" , "python" , "go" ], When omitted, the default is: Copy codeSamples : [ "curl" , "javascript" , "python" ] Available languages Language Config value cURL "curl" JavaScript "javascript" TypeScript "typescript" Python "python" Go "go" Ruby "ruby" Java "java" PHP "php" Rust "rust" C# "csharp" How it works Sourcey reads the operation's method, path, parameters, and request body from the spec. For each configured language, it generates an idiomatic request example using the standard HTTP library for that language (fetch for JavaScript, requests for Python, net/http for Go, etc.). The generated samples include: The correct HTTP method and URL Path and query parameters with placeholder values Request headers (content type, authorization if security schemes are defined) Request body for POST/PUT/PATCH operations Note Code samples are generated at build time from the spec. They're not hand-written templates. If your spec changes, the samples update automatically on the next build. Tip Order matters. Languages appear in the tab bar in the order you list them in the codeSamples array. Put the most common language for your audience first. ## CLI ### sourcey dev Path: `/docs/cli/cli-dev` Start a Vite dev server with SSR hot reload. Starts a development server that watches your config, markdown files, and OpenAPI spec for changes. Pages re-render instantly on save. Usage Copy sourcey dev [--port < numbe r > ] Flags Flag Alias Default Description --port -p 4400 Port to listen on Behavior The dev server reads sourcey.config.ts from the current directory and starts a Vite-powered SSR server. Changes to any of the following trigger a re-render: Markdown pages ( .md , .mdx ) OpenAPI spec files MCP spec files ( mcp.json ) Doxygen XML directories sourcey.config.ts The server performs full module graph invalidation on each change, ensuring every render reflects the latest state. There's no stale cache. Tip The dev server is for authoring and previewing. For production, use sourcey build and serve the static output. ### sourcey build Path: `/docs/cli/cli-build` Build static HTML documentation. Generates a complete documentation site as static HTML files. Two modes: site build (from sourcey.config.ts ) and quick build (from a standalone spec). Usage Copy # Site build (reads sourcey.config.ts) sourcey build [--output < di r > ] [--embed] [--quiet] # Quick build (single spec, no config) sourcey build < spe c > [--output < di r > ] [--embed] [--quiet] Flags Flag Alias Default Description --output -o dist Output directory --embed -e false Embeddable output (no html/body wrapper) --quiet -q false Suppress output Site build When run without a positional argument, sourcey reads sourcey.config.ts from the current directory and builds the full site. Copy sourcey build Copy Sourcey - building documentation site Pages: 14 Output: dist Time: 1.2s Quick build Pass a path to an OpenAPI spec to build a standalone API reference without a config file: Copy sourcey build ./openapi.yaml Copy Sourcey - generating docs from ./openapi.yaml Spec: My API v1.0.0 Operations: 24 Schemas: 12 Time: 0.9s Note Quick mode skips sourcey.config.ts entirely. It uses default theme settings and generates only the API reference; no markdown pages. Output The output directory contains standalone HTML files, a CSS file, a client-side JavaScript file, and a search index: Copy dist/ index.html introduction.html api.html sourcey.css sourcey.js search-index.json Every HTML file is self-contained. Serve with any static file server. AI output Site builds emit llms.txt and llms-full.txt alongside the HTML output. These provide an LLM-friendly index and full-text reference for the generated site, following the llms.txt convention. MCP tabs Site builds support MCP tabs alongside OpenAPI, Markdown, and Doxygen. Add source: mcp("./mcp.json") to a tab in your config. See MCP Integration for details. Quick build mode ( sourcey build ) only supports OpenAPI specs. ### sourcey validate Path: `/docs/cli/cli-validate` Validate an OpenAPI spec without building. Parses, dereferences, and normalizes an OpenAPI spec to check for errors. No output files are generated. Usage Copy sourcey validate < spe c > The argument is required. It can be a local file path or a URL. Success Copy sourcey validate ./openapi.yaml Copy Valid: My API v1.0.0 Operations: 24 Schemas: 12 Exit code: 0 Failure Copy Invalid: [error message describing the issue] Exit code: 1 What it checks Validation performs the same parsing pipeline as a full build: Parse the spec file (YAML or JSON) Dereference all $ref pointers Normalize the spec to sourcey's internal format Report the operation and schema count If any step fails, the error message identifies the issue: missing references, invalid schema definitions, unsupported spec versions, or malformed YAML/JSON. Tip Run sourcey validate in CI to catch spec errors before they break your docs build. It's fast (no rendering) and exits non-zero on failure. See OpenAPI Integration for how specs are used in the full build. MCP specs sourcey validate is for OpenAPI specs. To validate an mcp.json file, use mcp-parser : Copy npx mcp-parser validate ./mcp.json