On this page
Complete reference for selfdoc.json configuration options including project settings, themes, SEO, deployment, example validators, and branding.
#Configuration
selfdoc is configured via a selfdoc.json file in your project root. Run selfdoc init to generate a starter config interactively, or create one manually.
Five fields are required and nothing is inferred for them: base_url, search_engine, author, locales, and versions (or "unversioned": true in its place). source is optional -- a codeless project (a portfolio or personal site that is nothing but Markdown pages) declares none, and directives that extract from source code are then a hard error rather than an empty section. Everything else is optional and has defaults.
There is no top-level language key. Every source entry is an object naming its own path and language, so a polyglot repository declares one entry per language:
{
"source": [
{"path": "internal/", "language": "go"},
{"path": "web/src/", "language": "typescript"}
]
}Warning
base_url is required for deployment. Without it, canonical URLs, sitemaps, OG tags, and Atom feeds will have broken links. Set it to the URL where your site will be hosted (e.g., https://myproject.pages.dev).
#Config Reference
The table below lists every field recognized by selfdoc.json, including the field type, whether it is required, and a description of what it controls. Required fields have no default and must be provided explicitly.
| Field | Required | Description |
|---|---|---|
source | no | List of source entries to extract documentation from. |
base_url | yes | Base URL of the generated site, used for canonical links and SEO. |
version | no | Project version. When present, used by deploy instead of reading from the project manifest (VERSION, pyproject.toml or package.json). |
docs | no | Directory containing the handwritten Markdown documentation templates. It lives inside the tool-state directory, and a value outside it is refused as the layout selfdoc used before. |
output | no | Output directory for generated HTML files. It lives inside the tool-state directory, in the uncommitted cache. |
changelog | no | Path to the changelog document published as the site's changelog page, relative to the project root. Absent means the project root's CHANGELOG.md is used if it exists; declare it when that file is not this site's changelog. |
theme | no | Visual theme for the generated site. One of the themes selfdoc ships -- 'minimal', 'clean' or 'tinymoon'. A build's --theme flag overrides this for that build only, without writing anything back here. |
repo | no | GitHub repository URL shown in the site header. |
lang | no | BCP 47 language tag for the site content (e.g. 'en', 'pt-BR'). |
name | no | Explicit project name. Used as the single source of truth for the manifest name and the auto-generated API reference index description. When absent, the name is derived heuristically (single-source basename or project directory basename). |
description | no | Short description of the project, used in meta tags and SEO. |
branch | no | Git branch used for source links in the generated site. |
search | no | Search UI mode: icon button, full bar, or hidden. |
search_engine | yes | Search engine that answers this site's search UI. Required and never inferred: every site builds a search UI, so the engine behind it is declared, not defaulted. |
code_icons | no | Style of language icons shown on code blocks. |
line_numbers | no | Show line numbers in code blocks. |
run_button | no | Show a run button on code blocks for supported languages. |
page_nav | no | Show previous/next navigation links between pages. |
page_progress | no | Show a reading progress bar at the top of each page. |
glossary | no | Auto-generate a glossary page from dfn terms. |
coverage_threshold | no | Minimum fraction of public symbols that must be documented for selfdoc check to pass (0.0-1.0). Default 1.0 requires 100% coverage. |
feed_max_entries | no | Maximum number of entries in the Atom feed, sorted by most recent. |
lint_ignore | no | List of warning-severity lint rule IDs to suppress (e.g. 'SEO007', 'SEO008'). Error-severity codes cannot be suppressed and are refused at load. |
root_files | no | List of underscore-prefixed template paths in docs/ for root file generation. |
redirects | no | Page-level redirects expanded across all locale/version combos. |
deploy | no | Deployment configuration for publishing the generated site. |
directives | no | Custom directive mappings from directive name to source file path. |
examples | no | Validator command templates keyed by code-block language, used by 'selfdoc check' to execute fenced blocks marked 'validate'. Each template must contain the '{file}' placeholder. Absent means example validation is off. |
author | yes | The site's author: one Person, named in every page's structured data. Required -- there is no inferred author. |
twitter | no | Twitter/X handle (starts with @) for the twitter:site meta tag. |
feedback | no | Feedback collection configuration (at least one of webhook or ga required). |
branding | no | Landing page branding and call-to-action configuration. |
auto_detect | no | Automatic content detection settings for step guides and API entries. |
gen | no | Configuration for the gen command. |
gen_data | no | Configuration for the gen-data command. |
schema_types | no | Mapping from page type to schema.org @type (e.g. guide -> TechArticle). |
versions | no | List of documentation versions to build. |
unversioned | no | Declares that this project has no public version -- a personal site or portfolio that publishes no artifact. It replaces the 'versions' array (declaring both is an error) and is refused for a project that declares 'source', because code is the thing that gets released and therefore carries a version. An unversioned project's pages show no version badge, offer no version search filter and no version picker. |
locales | no | List of locales for multi-language documentation. |
unified | no | Configuration for unified multi-project documentation. |
posts | no | Blog post configuration. |
topology | no | Deployment topology for multi-project unified sites. |
assembly | no | Assembly configuration for unified site deployment. |
#Common Configurations
#Minimal Python project
{
"source": [{"path": "src/", "language": "python"}],
"base_url": "https://myproject.pages.dev",
"search_engine": "pagefind",
"author": {"name": "Jane Doe", "url": "https://janedoe.example"},
"versions": [{"version": "1.0.0"}],
"locales": [{"code": "en", "label": "English", "default": true}]
}#Go project with deployment
{
"source": [
{"path": "pkg/", "language": "go"},
{"path": "internal/", "language": "go"}
],
"base_url": "https://myproject.pages.dev",
"search_engine": "pagefind",
"author": {"name": "Jane Doe", "url": "https://janedoe.example"},
"versions": [{"version": "1.0.0"}],
"locales": [{"code": "en", "label": "English", "default": true}],
"repo": "https://github.com/user/myproject",
"branch": "main",
"deploy": {
"provider": "cloudflare-pages",
"project": "myproject"
}
}#Full-featured project with branding
{
"source": [{"path": "mylib/", "language": "python"}],
"base_url": "https://mylib.dev",
"versions": [{"version": "1.0.0"}],
"locales": [{"code": "en", "label": "English", "default": true}],
"docs": ".stricttools/docs/",
"output": ".stricttools/docs-cache/build/",
"description": "A toolkit for building great things.",
"repo": "https://github.com/user/mylib",
"branch": "main",
"lang": "en",
"theme": "minimal",
"search": "bar",
"search_engine": "pagefind",
"coverage_threshold": 0.8,
"author": {
"name": "Jane Doe",
"url": "https://janedoe.example",
"same_as": ["https://github.com/janedoe"]
},
"twitter": "@janedoe",
"deploy": {
"provider": "cloudflare-pages",
"project": "mylib"
},
"branding": {
"tagline": "Build great things.",
"cta_text": "Get Started",
"cta_link": "getting-started/",
"features": [
{
"title": "Fast",
"description": "Blazing fast builds with zero dependencies."
},
{
"title": "Flexible",
"description": "Works with Go, Python, TypeScript and six more languages."
}
]
},
"directives": {
"changelog": "scripts/changelog-directive.py"
}
}#Example Validators
The examples key maps a fenced-block language to the command that validates a snippet written in it. selfdoc check uses these commands for code blocks marked validate in their fence info string, writing each block to a scratch file and substituting its path for {file}:
{
"examples": {
"python": "uv run --directory python python {file}",
"go": "scripts/validate-example-go.sh {file}",
"ts": "scripts/validate-example-ts.sh {file}"
}
}Every command template must contain the {file} placeholder; a template without it is rejected when the config loads, since it would validate nothing. Keys are language names exactly as they appear after the opening fence, so a block opened with ```py needs a py entry, not a python one. Omitting examples entirely turns the feature off, and any validate marker in the docs then reports EXAMPLE003. See the Check Guide for the full behavior.