DocLang Format
DocLang is a JSON-based documentation format used by NIVAA. It separates content from presentation, allowing documentation pages to be rendered by any compatible frontend while maintaining rich structure and semantics.
Overview
Each documentation page is a JSON file with three top-level fields: title, lead (optional subtitle), and blocks (array of content blocks). The renderer processes blocks in order, choosing the appropriate component for each block type.
Page Structure
{
"title": "Page Title",
"lead": "Optional subtitle or intro text.",
"blocks": [
{ "type": "heading", "level": 2, "text": "Section Title" },
{ "type": "paragraph", "text": "Body text with **bold** and `code`." }
]
}| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Page title displayed as h1 |
lead | string | No | Subtitle text displayed below the title |
blocks | array | Yes | Ordered array of content blocks |
Inline Markup
Within any text field, the following inline markup is supported:
| Syntax | Renders As | Example |
|---|---|---|
bold text | Bold text | important becomes bold |
` code ` | Inline code | variable becomes monospace code |
link text | Hyperlink | Session Lifecycle becomes a link |
Text fields must not contain raw HTML. All formatting is done through inline markup syntax.
Block Types Reference
| Type | Category | Description |
|---|---|---|
heading | Text | Section heading (h2, h3, etc.) |
paragraph | Text | Body text with inline markup |
callout | Text | Highlighted note or warning box |
list | Text | Bulleted or numbered list |
steps | Text | Ordered process steps |
table | Data | Rows and columns of data |
code | Data | Syntax-highlighted code block |
badge-list | Data | Status badges with descriptions |
command-table | Data | Bot command reference table |
endpoint | Data | API endpoint documentation |
link-grid | Layout | Grid of linked cards |
flow | Diagram | Node-and-edge status flow diagram |
decision-tree | Diagram | Yes/no branching tree |
state-machine | Diagram | States and transitions |
scored-breakdown | Diagram | Weighted scoring dimensions |
architecture | Diagram | System architecture layers |
timeline | Diagram | Chronological event list |
swimlane | Diagram | Cross-actor workflow with horizontal lanes |
test-group | Testing | A named group of test cases with file, describe label, and per-test assertions |
Text Blocks
heading
{ "type": "heading", "level": 2, "text": "Section Title" }Properties: level (number, 2-4) and text (string).
paragraph
{ "type": "paragraph", "text": "Text with **bold** and `code` markup." }callout
{ "type": "callout", "variant": "info", "title": "Note", "text": "Important detail." }Variants: info (purple), warning (amber).
list
{ "type": "list", "ordered": false, "items": ["Item 1", "Item 2"] }steps
{ "type": "steps", "items": ["First do this.", "Then do that."] }Steps are always ordered (rendered as <ol>) and typically describe a sequential process.
Data Blocks
table
{ "type": "table", "headers": ["Col1", "Col2"], "rows": [["val1", "val2"]] }code
{ "type": "code", "header": "Example", "language": "json", "content": "{ \"key\": \"value\" }" }Properties: header (optional label above the block), language (syntax highlighting hint), content (raw code string).
badge-list
{ "type": "badge-list", "items": [
{ "label": "Scheduled", "variant": "blue", "description": "Initial state" }
] }Variants: blue, green, amber, red, purple, muted.
command-table
{ "type": "command-table", "commands": [
{ "command": "/sessions", "description": "Today's sessions", "detail": "Full explanation..." }
] }endpoint
{ "type": "endpoint", "method": "GET", "path": "/admin/students",
"auth": "Admin", "description": "List all students",
"params": [{ "name": "funnel", "type": "string", "description": "Filter" }],
"response": "{ ... }" }Layout Blocks
link-grid
{ "type": "link-grid", "columns": 2, "items": [
{ "title": "Link Title", "description": "Short description", "href": "/docs/page" }
] }Diagram Blocks
flow
{ "type": "flow",
"nodes": [
{ "id": "scheduled", "label": "Scheduled", "variant": "blue" },
{ "id": "active", "label": "Checked_In", "variant": "green" }
],
"edges": [
{ "from": "scheduled", "to": "active", "label": "optional edge label" }
]
}Represents a directed graph of status transitions. Node variants control color coding.
decision-tree
{ "type": "decision-tree", "title": "Cancel Flow",
"root": {
"label": "Is the session scheduled?",
"yes": { "label": "Proceed with cancel" },
"no": { "label": "Cannot cancel" }
}
}Recursive yes/no branching structure. Each node has label, and optional yes and no child nodes.
state-machine
{ "type": "state-machine", "title": "Callback Data",
"states": [
{ "id": "checkin_ID", "label": "Check in to appointment" }
],
"transitions": [
{ "from": "chg_ID", "to": "cnl_ID", "label": "Cancel" }
]
}scored-breakdown
{ "type": "scored-breakdown", "title": "Match Scoring",
"maxScore": 100,
"dimensions": [
{ "name": "Subject", "maxPoints": 25, "description": "Subject expertise match" }
]
}architecture
{ "type": "architecture", "title": "System Architecture",
"layers": [
{ "name": "Client", "items": ["SvelteKit Frontend", "Telegram Bot"] },
{ "name": "Edge", "items": ["CF Pages", "CF Worker"] }
],
"connections": [
{ "from": "SvelteKit Frontend", "to": "CF Pages", "label": "HTTPS" }
]
}timeline
{ "type": "timeline", "title": "Session Day",
"events": [
{ "time": "7:00 AM", "label": "Daily digest sent" },
{ "time": "~1 hour before", "label": "Pre-session reminder" }
]
}swimlane
{ "type": "swimlane", "title": "Posting Lifecycle",
"lanes": [
{ "label": "Parent", "color": "#3b82f6" },
{ "label": "Educator", "color": "#059669" },
{ "label": "Coordinator", "color": "#d97706" },
{ "label": "System", "color": "#552c7d" }
],
"steps": [
{
"lane": "Parent",
"action": "Posts tutoring need",
"triggers": "Notification to matching tutors",
"visibility": "Educators see on Browse",
"backend": "posting.status = 'Open'",
"next": "Educator applies"
}
]
}Renders horizontal swim lanes with step cards flowing left-to-right. Each lane represents an actor (e.g. Parent, Educator, System). Steps are placed in their lane and connected by arrows that curve across lanes when the actor changes.
| Field | Type | Required | Description |
|---|---|---|---|
lanes | array | Yes | Array of lane definitions with label (string) and optional color (hex) |
steps | array | Yes | Ordered array of step objects placed in lanes |
steps[].lane | string | Yes | Which lane this step belongs to (must match a lane label) |
steps[].action | string | Yes | Primary action text shown in the step card |
steps[].triggers | string | No | Side-effect or notification triggered by this step |
steps[].visibility | string | No | Who can see or is affected by this step |
steps[].backend | string | No | Backend state change (shown in monospace) |
steps[].next | string | No | Description of what happens next (for documentation only, not rendered) |
Testing Blocks
test-group
Renders a labeled group of test cases with a file badge, describe block name, test count, and a row per test showing method, path, and assertion. Used to document test coverage in the docs site.
{
"type": "test-group",
"file": "api.test.ts",
"describe": "Session Lifecycle",
"tests": [
{ "method": "POST", "path": "/appointments/:id/confirm", "assertion": "200 — package deducted" },
{ "method": "POST", "path": "/appointments/:id/dispute", "assertion": "200 — package restored" },
{ "assertion": "Flow-only assertion with no HTTP method" }
]
}| Field | Type | Required | Description |
|---|---|---|---|
file | string | Yes | Filename displayed as a dark badge (api.test.ts, shapes.test.ts, flows.test.ts) |
describe | string | Yes | The describe() block name shown as the group heading |
tests | array | Yes | Array of test case objects |
tests[].method | string | No | HTTP method — rendered as a colour-coded badge (GET, POST, PATCH, PUT, DELETE) |
tests[].path | string | No | URL path — rendered in monospace with purple tint |
tests[].assertion | string | Yes | What the test asserts — plain prose description |
For flow tests that don't map cleanly to a single endpoint, omit method and path and use only assertion. The block renders gracefully with just the assertion text.
Navigation Structure
The sidebar navigation is defined in nav.json as an array of sections. Each section has a title, optional defaultOpen boolean, and an items array. Each item has a label (display text) and a slug (URL path segment relative to /docs/).
[
{
"title": "Getting Started",
"defaultOpen": true,
"items": [
{ "label": "Overview", "slug": "" },
{ "label": "Architecture", "slug": "architecture" }
]
}
]Complete Example
A minimal but complete documentation page:
{
"title": "My Feature",
"lead": "A brief introduction to this feature.",
"blocks": [
{ "type": "heading", "level": 2, "text": "How It Works" },
{ "type": "paragraph", "text": "This feature uses **blind matching** to connect users." },
{ "type": "callout", "variant": "info", "title": "Note", "text": "Only `Admin` users can access this." },
{ "type": "steps", "items": [
"User submits a request.",
"System processes and scores it.",
"Coordinator reviews and approves."
] },
{ "type": "table", "headers": ["Status", "Meaning"], "rows": [
["**Active**", "Currently in use"],
["**Closed**", "No longer available"]
] },
{ "type": "code", "header": "API Response", "language": "json", "content": "{\n \"ok\": true,\n \"data\": { \"id\": 1 }\n}" }
]
}