---
summary: 'First-class documentation: global namespaces, versioned, markdown-native,
  hybrid-searchable, AI-native.'
title: Docs subsystem (this!)
path: concepts/docs-subsystem
status: published
---

# Docs subsystem

The page you're reading right now is served by the docs subsystem — a
separate first-class module that lives alongside regular content but with
its own model designed specifically for documentation.

## What makes it different

| | Regular content | Docs subsystem |
|---|---|---|
| Storage | `contents` + field rows | `doc_pages` rows, body is raw markdown |
| Site-scoped? | Yes | No — namespaces are global |
| Versions | One | Many (full-copy per version) |
| Hierarchy | Yes (parent_id) | Yes (parent_id) |
| Address | Site + path | Namespace + version + path |
| Markdown native | No | Yes — GFM rendered server-side |
| Sub-products | Via taxonomy | Via `parent_namespace_id` |
| Visibility | Per-site content perms | `public` / `authenticated` / `restricted` per namespace |
| Public site mounts | Direct URL | `site_doc_mounts` (longest-prefix wins) |
| AI surface | MCP `manage_content` | MCP `manage_documentation` + REST + Python SDK |

## Mental model

- **Namespace** = one product (`scaigrid`, `scaibot`, `scaicms`). Global.
  Optional parent for sub-products (so `scaibot` can declare its parent as
  `scaigrid` without changing URLs).
- **Version** = `v1`, `v2`, … inside a namespace. Pages are deep-copied on
  fork; versions are independent thereafter. Exactly one default.
- **Page** = a markdown document at a slash-joined `path` inside a version
  (`models/training`).

Every page is uniquely identified by `(namespace, version, path)`. URLs
follow the same shape. Mounts choose a URL prefix per site.

## Mounting on a site

```
namespace `scaicms` mounted at `/docs/scaicms`  on the ScaiLabs site
       └─ visibility=public

namespace `scaicms-internal` mounted at `/docs/scaicms/internal`
       └─ visibility=restricted, read_role_slugs=[docs_internal]
```

Longest-prefix wins, so internal docs nest cleanly under the public ones
without conflicts.

## Restricted docs flow

When an anonymous user hits a restricted URL on the delivery service:

1. The middleware checks for a session cookie.
2. No cookie → 303 redirect to `/docs/login?next=<original>`.
3. User signs in (same credentials as the admin UI — backend mints a JWT
   into an HttpOnly cookie).
4. The role check runs: user must hold one of the namespace's
   `read_role_slugs`. Authorised → page renders. Not authorised → 403.

The cache key includes the auth scope so signed-in users don't see the
anonymous cache, and vice versa.

## Searching, deep-linking

Markdown is chunked by heading on index. Each chunk gets an embedding and
indexes into Weaviate's `DocPage` collection. A search hit carries both the
page path and the chunk anchor:

```
{namespace}/{path}#{anchor}
```

so a search agent can produce links that jump straight to the relevant
section.

## Further reading

- [Agent guide](/docs/scaicms/concepts/mcp) — feed it to an LLM for
  read/write capability.
- [Reference → docs API](/docs/scaicms/reference/api-endpoints) — full REST
  surface for the docs system.
