Skip to content

Writing the documentation

The documentation is a MkDocs site with the Material theme, built from docs/ and configured in mkdocs.yml.

Preview and build

Run MkDocs through the backend project so the right plugins are installed:

DISABLE_MKDOCS_2_WARNING=true uv run --project backend --group docs mkdocs serve

Use mkdocs build --strict instead of serve to find broken links. The DISABLE_MKDOCS_2_WARNING variable only silences a banner printed by one of the plugins. The site is built and published by the docs GitHub workflow.

Layout

Folder Audience Content
getting-started/ People hosting Endurain Install, reverse proxy, updates, scaling, troubleshooting
features/ Users and administrators What Endurain does and how to use it
integrate/ People building on the API Authentication, errors, supported types
developer-guide/ Contributors Module structure, ingestion, events, UX guidelines
reference/ Contributors Generated Python API reference

Every page must be listed under nav: in mkdocs.yml. Name files with hyphens (export-import.md).

Moving or renaming a page

Published URLs are linked from outside the docs: README.md, .env.example, docker/start.sh, blog posts and other sites. When you move or rename a page:

  1. Add the old path to redirect_maps under the redirects plugin in mkdocs.yml.
  2. Search the repository for the old path and update the links, including AGENTS.md, which links to some developer-guide files.

Diagrams

Mermaid diagrams are supported. Use a fenced block with the mermaid language:

```mermaid
flowchart LR
    A[Upload] --> B[Parse] --> C[Store]
```

The Mermaid library is loaded in the browser, so readers need internet access to see the rendered diagram. Keep diagrams small and say the same thing in the surrounding text.

Tables generated from the code

Some tables are filled in from the backend source when the docs are built, so they cannot drift. Put a marker on its own line where the table belongs:

Marker Fills in
` Scope
----- -----------
profile Privileges over user's own profile
users:read Read privileges over users
users:write Write privileges over users
sessions:read Read privileges over sessions
sessions:write Create/edit/delete privileges over sessions
gears:read Read privileges over gears
gears:write Write privileges over gears
activities:read Read privileges over activities
activities:write Write privileges over activities
activities:upload Upload privileges over activities
followers:read Read privileges over the follower/following graph
followers:write Follow, unfollow, accept and remove followers
health:read Read privileges over health data
health:write Write privileges over health data
health_targets:read Read privileges over health targets data
health_targets:write Write privileges over health targets data
notifications:read Read privileges over notifications
notifications:write Write privileges over notifications
server_settings:read Read privileges over server settings
server_settings:write Write privileges over server settings
identity_providers:read Read privileges over identity providers
identity_providers:write Write privileges over identity providers
| Every scope inSCOPE_DICT`
` Scope
----- -----------
activities:upload Upload privileges over activities
` The scopes an API key may hold
` Method
------ ---
GET /profile/api_keys
POST /profile/api_keys
PATCH /profile/api_keys/{api_key_id}/revoke
DELETE /profile/api_keys/{api_key_id}
` The API key management routes
| Status |type` Title
------ ------
404 urn:endurain:error:not-found
403 urn:endurain:error:permission-denied
400 urn:endurain:error:invalid-input
409 urn:endurain:error:conflict
412 urn:endurain:error:precondition-failed
406 urn:endurain:error:unsupported-format
415 urn:endurain:error:unsupported-media-type
413 urn:endurain:error:payload-too-large
503 urn:endurain:error:service-unavailable
502 urn:endurain:error:upstream-error
500 urn:endurain:error:internal-error
` The error types and their HTTP statuses
` Tier
---- -----
DEFAULT 120/minute
WRITE 30/minute
SENSITIVE 10/minute
UPLOAD 20/minute
PROVIDER_SYNC 6/minute
` The rate-limit tiers

The code is in mkdocs_hooks/auth_docs.py. It reads the backend with Python's ast module and does not import it, so the docs build needs no backend dependencies. If a source it reads is moved or renamed, the build fails and you update the hook. To add a table, write a function that returns a Markdown table and add it to GENERATORS.

Python API reference

Pages under reference/ use mkdocstrings. A section is a heading followed by a directive naming the module:

## Service

::: backend.app.modules.followers.service
    handler: python
    options:
      docstring_style: google

The text comes from the docstrings, which use the Google style (Args, Returns, Raises). Fix a wrong reference page by fixing the docstring. Add a new module to the page of its area, or add a page and list it in nav:.

Reusing fragments

Shared HTML such as the newsletter form and the secret generators lives in docs/_snippets/ and is included with --8<-- "_snippets/name.html".