This file documents the documentation site (`/docs`) - prose pages, API reference generation, search, and the interactive tester. Claude Code auto-loads it whenever a file in this directory is read or edited. ## Routing overview - `(none)` - `docs.py` (`docs/` package), the documentation site (prose pages + API reference). See `DOCS_PAGES` below. ## Documentation site (`/docs`) `routers/docs/ package` serves the docs. `DOCS_PAGES` (`routers/docs/pages.py`, re-exported from the `routers/docs` package; handlers in `routers/docs/views.py`) keeps curated prose pages (`kind: "prose"`, each with its own template under `templates/docs/.html`) and spreads `api_doc_pages()` from `devplacepy/docs_api.py` for every API reference page. Prose pages grouped by `section`: `General` (`index`, `getting-started`, `devii`, `dashboard`, `media-gallery`, `notification-settings`), admin-only `Devii internals` (`devii-*`), admin-only `Services` (`services-*`, documenting the `BaseService` framework and every background service including the live data at `GET /admin/services/data`), and admin-only `Production` (`production-*`, documenting the deployment). A page is admin-gated by `"admin": True`; search/export pick it up automatically by slug and respect the admin flag - no extra wiring. ## Audience tiers and navigation `DOCS_PAGES` entries take optional `admin: True` (hidden + 404 for non-admins, but still indexed and surfaced only to admins by `docs_search`) and `section: "..."` (a nested sidebar group rendered by `docs_base.html`). The sidebar groups `section`s under four ordered **audience tiers** (`AUDIENCES` in `routers/docs/pages.py`): `Start here` (General), `Build with the API` (API, Components, Styles), `Contribute and internals` (Architecture, Services, Devii internals, Bots internals, Testing, Claude Code), and `Operate` (Administration, Production). `nav_groups(visible_pages)` builds the `[(audience, [(section, [pages])])]` tree from the flat visible-page list (so a section's pages collect under one heading regardless of `DOCS_PAGES` order or the API/Administration interleave from `api_doc_pages()`); `views.py` passes it as `nav`, and `docs_base.html` renders an audience super-header (`.sidebar-tier`) above each section subheading (`.sidebar-subheading`). `DOCS_PAGES` stays the canonical list for search/export/routing - the tiering is sidebar-only. The public `getting-started` page (`SECTION_GENERAL`) is the new-contributor on-ramp (install/run, the four-faces workflow, validation); gate its deep-internals links with `{% if is_admin(user) %}` so guests get no 404s. Keep one canonical home per concept: the `auth` API group intro in `docs_api.py` defers method detail to the `authentication` prose page rather than re-listing the four methods. The member-facing `devii` prose page is functional; admins also get a `Devii internals` section of `devii-*` technical subpages. ## Single source of truth `docs_api.py` `API_GROUPS` defines each reference page and its endpoints (method, path, auth, params, notes, sample_response). Add an endpoint there and the page, sidebar link, code examples, and interactive runner appear automatically. ## Downloads `devplacepy/docs_export.py`: `/docs/download.md` returns the entire docs as one Markdown file; `/docs/download.html` returns a single **self-contained** HTML (vendored `marked` + `highlight.js` + theme inlined, the Markdown embedded base64 and rendered on open - works offline). Both are admin-filtered like the rest of the docs and reuse the same group/prose sources. Routes are declared before `/docs/{slug}.html` so `download.html` isn't caught by the slug pattern. ## Docs search (`/docs/search.html`) A backend-rendered BM25 search over all docs pages, in `devplacepy/docs_search.py`. The corpus = prose page text (template stripped of Jinja/HTML) + each API group's intro/endpoints + the live services group; the inverted index (postings + idf) is built **once** lazily (`get_index()`, cached module-global) so a query is just postings lookups (~120us). `docs.py` special-cases `slug == "search"` (before the page registry) and renders `docs/_search.html` inside `docs_base.html` (`kind == 'search'`). Admin-only pages are filtered from results for non-admins, exactly like the sidebar. Snippets are HTML-escaped then wrapped in `` (XSS-safe). `_strip` removes `