Page Templates
Copy the template that matches what you are writing, then fill it in. The structure is the point — readers navigate these docs by shape as much as by content.
Read the style guide first if you have not.
Where files go
Section titled “Where files go”Which set a page belongs to is decided by one question: is it useful without Oculis? Sizing GPU
memory is, so it lives in ai/. The CLI reference is not, so it lives in oculis/.
| Set | Path | Holds |
|---|---|---|
| AI documentation | src/content/docs/ai/ |
Vendor-neutral AI infrastructure material. |
| Oculis | src/content/docs/oculis/ |
Product and component material. |
| Contribute | src/content/docs/contribute/ |
How these docs are written. |
Inside a set there is one directory per family, and the family’s primary page is its index.mdx:
ai/capacity-planning/index.mdx -> /ai/capacity-planning/ai/capacity-planning/benchmarking.mdx -> /ai/capacity-planning/benchmarking/The sidebar is explicit rather than autogenerated, so a new page must be registered in
astro.config.mjs — inside the family group it belongs to. That is deliberate: order, labels, and
family membership are editorial decisions.
A page also needs an entry in src/data/catalog.ts if it should appear in the hub homepage
directory. Only add entries that resolve to real published pages; the build fails on a dead link.
Moving a page between sets means moving the file, moving its sidebar entry, and adding a permanent
redirect in public/_redirects pointing at the final URL — npm run check:redirects fails the
build on a chain.
Configuration guide template
Section titled “Configuration guide template”For any page that tells someone to change a setting.
---title: 'Configuring <Thing>'description: 'One sentence, written for a search result. What this does and who needs it.'---
import { Aside, Steps, Tabs, TabItem, CardGrid, LinkCard } from '@astrojs/starlight/components';import PageMeta from '../../../../components/PageMeta.astro';import Prerequisites from '../../../../components/Prerequisites.astro';import Verify from '../../../../components/Verify.astro';import ErrorCode from '../../../../components/ErrorCode.astro';import DiagnosticMatrix from '../../../../components/DiagnosticMatrix.astro';
<PageMeta minVersion="v1.4.0" hardware="NVIDIA A100 / H100" requires="CUDA 12.1+" difficulty="Intermediate" impact="Rolling restart"/>
One paragraph: what this configures, and the problem it solves. Lead with the outcome.
## What this changes
```text ASCII diagram of the before/after topology. Keep it under 80 columns.```
Before: <one line>. After: <one line>.
<Prerequisites checkCommand="oculis status --check-deps">
- **Oculis Collector** `v1.4.0` or later- **Hardware:** exact requirement- **Network ports:** which, inbound or outbound- **Permissions:** what the operator must be able to do
</Prerequisites>
## Step 1 — <Imperative verb phrase>
<Tabs syncKey="interface"><TabItem label="CLI / YAML">
```yaml title="oculis-config.yaml" {3-5}oculis: thing: key: value```
</TabItem><TabItem label="Python">
```python title="configure.py"from oculis import Thing```
</TabItem><TabItem label="Helm">
```yaml title="values.yaml"thing: key: value```
</TabItem></Tabs>
**Parameters that matter most:**
| Parameter | Why it matters || --------- | ---------------------------------------------------- || `key` | What breaks if it is wrong, and how to pick a value. |
## Step 2 — Apply
<Steps>
1. **Validate.**
```bash oculis config validate --file oculis-config.yaml --explain ```
2. **Apply.**
```bash oculis apply --file oculis-config.yaml --strategy rolling ```
</Steps>
<Verify summary="What a passing result proves, in one sentence.">
**1. <What this check establishes>.**
```bashoculis <command>```
```text title="Expected output" frame="terminal"[PASS] Real output, copied from a real run.```
If this shows X instead, that means Y — go to <ErrorCode code="ERR_OCULIS_…" />.
</Verify>
## Edge cases and known limitations
- **<The thing that quietly bites>.** Why, and what to do instead.- **<An incompatibility>.** Name the hardware or version.
## Failure modes this configuration produces
<DiagnosticMatrix category="<Category>" filterable={false} />
## Next steps
<CardGrid> <LinkCard title="…" description="…" href="/…/" /></CardGrid>Troubleshooting page template
Section titled “Troubleshooting page template”For a page organized around symptoms rather than tasks.
---title: '<Subsystem> Troubleshooting'description: 'Diagnose <specific failures> in <subsystem>.'---
import { Aside, Steps, Tabs, TabItem, CardGrid, LinkCard } from '@astrojs/starlight/components';import PageMeta from '../../../../components/PageMeta.astro';import Verify from '../../../../components/Verify.astro';import ErrorCode from '../../../../components/ErrorCode.astro';import DiagnosticMatrix from '../../../../components/DiagnosticMatrix.astro';
<PageMeta minVersion="v1.4.0" difficulty="Advanced" />
One paragraph framing how failures in this subsystem divide up. Give the reader a mental modelbefore the table.
Start here:
```bashoculis status --check-deps --verbose```
<DiagnosticMatrix category="<Category>" filterable={false} />
## <Failure mode, named as the reader would say it>
**Signature:** <ErrorCode code="ERR_OCULIS_…" />
```text frame="terminal"The actual log line, verbatim.```
### Why it happens
The mechanism. This is what makes the fix stick rather than being cargo-culted.
### Resolution
<Steps>
1. **<Diagnostic step>.**
```bash oculis <command> ```
2. **<Fix>.**
```yaml title="oculis-config.yaml" {3} oculis: thing: key: new-value ```
</Steps>
<Aside type="caution" title="<The wrong fix people try first>"> Why it makes things worse.</Aside>
## <Next failure mode>
…
<Verify summary="Run after any change in this area.">
```bashoculis <command>```
```text title="Expected output" frame="terminal"[PASS] …```
</Verify>
## Next steps
<CardGrid> <LinkCard title="…" description="…" href="/…/" /></CardGrid>Optimization blueprint template
Section titled “Optimization blueprint template”For pages that trade one property for another.
---title: '<Optimization area>'description: '<What improves, and what it costs.>'---
import { Aside, Steps, Tabs, TabItem, CardGrid, LinkCard } from '@astrojs/starlight/components';import PageMeta from '../../../../components/PageMeta.astro';import Prerequisites from '../../../../components/Prerequisites.astro';import Verify from '../../../../components/Verify.astro';
<PageMeta minVersion="v1.4.0" hardware="…" difficulty="Advanced" impact="Rolling restart" />
State the two things being traded, and how to tell which one is your problem.
<Prerequisites checkCommand="oculis status --check-deps">
- **[A benchmark baseline](/ai/capacity-planning/benchmarking/)** — mandatory- **[Telemetry configured](/ai/telemetry-observability/)**
</Prerequisites>
## Step 0 — Find out what is actually slow
```bashoculis trace get <request-id> --format tree```
| Dominant span | Real problem | Fix || ------------- | ------------ | --- || `…` | … | … |
<Aside type="danger" title="If <the wrong problem> dominates, stop"> Why tuning here will not help.</Aside>
## <Technique>
What it does, in two sentences.
```yaml title="oculis-config.yaml" {3}oculis: upstreams: - engine: setting: value```
| Option | Effect | Cost || ------ | ------ | ---- || `a` | … | … |
Confirm it is engaging:
```bashcurl -s http://localhost:9090/metrics | grep <metric>```
<Verify summary="Compares against the baseline. A tuning change without a before-and-after is a guess.">
```bashoculis bench run --compare baseline.json --duration 300s```
```text title="Expected output" frame="terminal" baseline current delta metric ... ... ...[PASS] No regression in error rate.```
</Verify>
## Edge cases and known limitations
- **<What this costs>.**
## Next steps
<CardGrid> <LinkCard title="…" description="…" href="/…/" /></CardGrid>Adding an error code
Section titled “Adding an error code”Codes live only in src/data/errors.ts.
{ code: 'ERR_OCULIS_NEW_THING', http: 503, category: 'Inference & Streaming', severity: 'error', symptom: 'What the operator observes, in their words.', logSignature: 'the actual grep-able log fragment', rootCause: 'Why it happens, mechanically.', resolution: 'The first action to take.', guide: '/troubleshooting/<page>/#<anchor>',},Then reference it inline as <ErrorCode code="ERR_OCULIS_NEW_THING" />. The build fails on an
unknown code, which is how prose and the catalog stay in sync.
Local development
Section titled “Local development”npm installnpm run dev # http://localhost:4321npm run build # includes astro checknpm run format