Documentation Module
The optional, default-enabled documentation module publishes reviewed
Markdown as public pages rendered by the active frontend theme. It is intended
for version-controlled project, developer, operator, and customer material.
Tenant-authored database content remains owned by the Page module, and PHPDoc
keeps its separate technical surface.
Request And Locale Resolution
The module registers localized GET /docs and GET /docs/{path} routes. The
index redirects to the first public manifest entry, which is the
complete k0smos reference. A page request follows
this sequence:
- resolve the navigation locale from the request;
- resolve redirects and published paths in that locale;
- when no matching page exists, retry with the tenant's
i18n.documentation_locale; - use
enwhen that setting is missing or malformed; - return
404when neither catalog publishes the requested path.
A document in the active navigation locale always wins. Fallback content is identified visibly and keeps the visitor's navigation URL. Locale alternates are matched by stable document ID rather than by filename.
Catalog And Navigation
Each locale owns doc/public/{locale}/navigation.json. Its public entries are
sorted by order; the first entry is the /docs destination and also starts
previous/next navigation. Every source must be a lowercase locale-relative
path and must satisfy source === path . '.md'.
The sidebar mirrors the source tree without requiring synthetic Markdown index files. Root documents are primary links. Directory segments become navigation groups, nested directories become nested groups, and the document title stays the clickable leaf. Group order is determined by the first document in each directory, so manifest order remains the deliberate reading order.
The parent field is independent from folder grouping. It supplies editorial
breadcrumbs; the current English catalog points every secondary document back
to the complete reference. Stable IDs must not change when files or public URLs
move. Put retired URLs in redirects so existing links receive a permanent
redirect.
Safe Markdown Rendering
DocumentationCatalog resolves only visibility: public entries. Before a
source is read, it rejects traversal and invalid characters, resolves both the
locale root and source with realpath(), and verifies that the file remains
inside doc/public/{locale}.
DocumentationRenderer then performs the following steps:
- rewrite
doc:stable-id#optional-fragmentlinks through the active catalog; - convert Markdown with CommonMark core, tables, and heading permalinks;
- strip raw HTML and reject unsafe link schemes;
- assign lowercase, unprefixed IDs directly to
h1throughh6headings; - extract
h2andh3headings from the rendered DOM for the page index.
Generated index links, visible heading permalinks, authored same-page links, and cross-document fragments therefore share the same target. The theme applies a scroll offset to every heading so fixed navigation does not cover it.
The canonical Plates template renders breadcrumbs, locale fallback status, folder navigation on desktop and mobile, Markdown content, previous/next links, and the per-page heading index. Basic reading and navigation require no JavaScript. The default theme adds responsive layout, dark mode, overflow-safe code and tables, print rules, and progressively enhanced code-copy controls.
Caching And Search
The catalog caches parsed navigation by manifest modification time. Rendered HTML and heading indexes are cached by source path, modification time, and resolved Markdown content. The page response declares a five-minute public cache lifetime with one hour of stale-while-revalidate coverage. A long-running PHP worker may still need a restart after deployment, and clients may need a hard refresh while an older response remains cached.
Public entries contribute to frontend lexical search. When the optional vector store is configured and healthy, the same strict public allowlist contributes rebuildable vector documents; failure falls back to lexical search. Markdown files, not either search index, remain authoritative.
Authoring And Verification
Add a page by creating doc/public/{locale}/{path}.md and registering the same
{path} and {path}.md in the locale manifest. Cross-document links use the
stable-ID form shown by the Vision section,
with an optional heading fragment. Do not link directly to .md files or
traverse with ../.
Run the offline publication gate after every catalog or Markdown change:
php bin/console documentation:validate
It checks manifest shape, source containment, exact source coverage, IDs, paths, redirects, parents, headings, unsafe HTML and URLs, stable document links, and locale gaps. The PHPUnit publication contract additionally checks that every authored fragment resolves to an actual rendered heading.
For a browser review through the real tenant bootstrap and active theme, run:
php bin/console documentation:preview
The preview server accepts loopback hosts and ports 1024–65535 only. Template or style changes also require the maintainer-owned default-theme build:
cd template/default && npm run build && cd ../..
The module commits no generated HTML, stores no documentation in the database, and has no schema migration.