Doc
Doc protocol schemas
Package Documentation Metadata Protocol (ADR-0046)
One doc item per Markdown file under the package's flat src/docs/
directory (no subdirectories — flatness is the contract that keeps
cross-references stable). The CLI compiles each file into this shape at
build time; TS-first stacks may also declare items inline via
defineStack({ docs: [...] }).
Identity model: name = filename stem (lowercase snake_case). A namespace
prefix (crm_lead_guide) is a recommended convention, no longer required:
per ADR-0048, single-doc resolution is package-scoped (getItem('doc', name, packageId) via ?package= on the detail route), so two packages may ship a
doc with the same bare name and each resolves within its own package — just
like page/dashboard/report. The prefix stays useful for readable,
globally-unique filenames but is not load-bearing for uniqueness.
Docs are inert data: the kernel registers them without parsing
content, and they participate in no runtime behavior. Renderers
resolve relative links between docs ([guide](./crm_lead_guide.md))
by stripping ./ and .md to obtain the target doc name.
Source: packages/spec/src/system/doc.zod.ts
TypeScript Usage
import { DocSchema } from '@objectstack/spec/system';
import type { Doc } from '@objectstack/spec/system';
// Validate data
const result = DocSchema.parse(data);Doc
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| name | string | ✅ | Doc name (= filename stem, snake_case; namespace prefix recommended, not required) |
| label | string | optional | Display title; defaults to the first # heading, then the name |
| description | string | optional | One-line summary for listings; from frontmatter description: |
| content | string | ✅ | Raw Markdown content (CommonMark + GFM) |
| order | number | optional | Sort key within a book group (ADR-0046 §6) |
| group | string | optional | Explicit book-group key (ADR-0046 §6); rules usually suffice |
| tags | string[] | optional | Membership tags matched by a book group's include: { tag } rule (ADR-0046 §5) |
| translations | Record<string, { label?: string; description?: string; content: string }> | optional | Per-locale {label?,description?,content} variants; the base doc is the fallback |
| _lock | Enum<'none' | 'no-overlay' | 'no-delete' | 'full'> | optional | Item-level lock — controls overlay & delete (ADR-0010). |
| _lockReason | string | optional | Human-readable reason shown when a write is refused by _lock. |
| _lockSource | Enum<'artifact' | 'package' | 'env-forced'> | optional | Layer that set _lock (artifact | package | env-forced). |
| _provenance | Enum<'package' | 'org' | 'env-forced'> | optional | Origin of the item (package | org | env-forced). |
| _packageId | string | optional | Owning package machine id. |
| _packageVersion | string | optional | Owning package version. |
| _lockDocsUrl | string | optional | Optional documentation link surfaced next to _lockReason. |