Skip to content

Editing These Docs ​

This site is a workspace app like any other: apps/docs, built with VitePress. Documentation lives next to the code it describes and ships through the same pipeline.

Running it ​

bash
pnpm docs                                # from the repo root
pnpm --filter @playpals/docs dev         # equivalent

Opens on http://localhost:5173 with hot reload.

bash
pnpm --filter @playpals/docs build       # static site → .vitepress/dist
pnpm --filter @playpals/docs preview     # serve the built output

Structure ​

apps/docs/
├── .vitepress/
│   ├── config.ts              site config, nav, sidebar
│   ├── markdown/mermaid.ts    ```mermaid fence → <Mermaid> component
│   └── theme/
│       ├── index.ts           theme entry, registers <Mermaid>
│       ├── custom.css         PlayPalz brand colours
│       └── Mermaid.vue        client-side diagram rendering
├── public/                    logo, favicon
├── index.md                   home page
├── guide/  architecture/  services/  database/
├── api/    mobile/  infrastructure/  operations/
├── reference/  platform/
├── Dockerfile
└── nginx.conf

Adding a page ​

  1. Create the markdown file in the right directory.
  2. Add it to the sidebar in .vitepress/config.ts. A page not in the sidebar is unreachable.
  3. Link to it from related pages.

Links are root-relative and omit the .md extension (cleanUrls is on):

md
See [Realtime](/architecture/realtime).

The build fails on a dead link (ignoreDeadLinks: false), which is deliberate — a broken cross-reference is caught before it ships.

Diagrams ​

Mermaid works in a plain fenced block:

md
```mermaid
graph LR
    A[Client] --> B[api]
    B --> C[(PostgreSQL)]
```

A custom markdown-it rule replaces the fence with a <Mermaid> component that renders client-side and re-renders when the reader toggles light/dark. Sequence diagrams, ER diagrams, flowcharts, and Gantt charts are all used in these docs.

Callouts ​

md
::: tip
Helpful aside.
:::

::: warning
Something that will surprise you.
:::

::: danger
A defect, a security issue, or an irreversible action.
:::

::: info
Neutral context.
:::

Use warning for behaviour that differs from what a reader would reasonably expect, and danger for real defects, security gaps, and destructive commands. Do not use them for emphasis.

Status badges ​

html
<span class="pp-pill pp-pill--live">Shipped</span>
<span class="pp-pill pp-pill--partial">Partial</span>
<span class="pp-pill pp-pill--planned">Planned</span>

House style ​

Say what is true, including when it is unflattering. These docs name specific defects with file paths and suggested fixes. That is the point — a developer who hits the ogun /admin prefix bug at 2am should find it documented, not discover it.

Point at the code. apps/api/src/lib/roomAccess.ts is more useful than "the room access logic".

Explain why, not just what. The reader can read the code for what. Document the reasoning that is not in the code — why esu calls back into the API, why the socket ingress is separate, why anansi is a singleton.

Keep code excerpts short and real. Copy from the source rather than paraphrasing; a stale snippet is worse than none.

Line length ~100 characters, matching Prettier's 120 with margin.

Keeping it current ​

Update the docs in the same pull request as the change:

You changedUpdate
A routeThe relevant API Reference page
An environment variableEnvironment Variables
A socket eventSocket Events
The schemaDomain Models
A deployment manifestKubernetes
A service's behaviourThat service's page

If you fix one of the defects documented here, remove the callout in the same PR.

Deployment ​

The site builds to static HTML and is served by nginx on port 8080 in a distroless-style Alpine image, running as the non-root nginx user.

bash
./scripts/build-docs.sh "$(git rev-parse --short HEAD)"
infra/helm/deploy.sh docs "$(git rev-parse --short HEAD)"
PropertyValue
Imageregistry.digitalocean.com/playpalzproduction/docs
Helm valuesinfra/helm/values/production/docs.yaml (release playpalz-docs)
Replicas2
Port8080
Hostdocs.playpalz.gg
Resources10m CPU / 32Mi requested — the smallest workload in the cluster

./scripts/build-all.sh includes docs.

Restricting access

The docs describe internal architecture, known defects, and operational procedures. The ingress has commented-out basic-auth annotations ready to enable:

bash
htpasswd -c auth <username>
kubectl create secret generic docs-basic-auth --from-file=auth

Then uncomment the three auth-* annotations on playpalz-docs-ingress in infra/helm/values/production/platform.yaml and run infra/helm/deploy.sh platform. Worth doing before the site is publicly reachable.

First-time setup ​

  1. Add a docs A record — dns.tf already contains it when manage_dns = true, otherwise create it manually pointing at the LoadBalancer IP.
  2. ./scripts/build-docs.sh, then infra/helm/deploy.sh docs <commit>.
  3. Watch kubectl get certificate until playpalz-docs-tls reports Ready.

Notes on the build ​

  • .dockerignore excludes **/*.md for the service images, with an explicit !apps/docs/**/*.md exception — without it the docs image would build an empty site.
  • nginx try_files $uri $uri.html is what makes cleanUrls work: VitePress emits getting-started.html but links to /getting-started.
  • Hashed assets get a one-year immutable cache; HTML must revalidate so a redeploy is picked up immediately.

Internal documentation — PlayPalz platform