Authoring conventions
These docs are Astro Starlight MDX. This page is the style contract every page follows: which components to reach for, how to escape the characters MDX chokes on, how to mark deploy-honesty with badges, and the one rule that fails the build if you break it — env-var names only, never values.
The single best reference is a finished page. Read Add a new generation tool worker — it is the quality bar, and it uses almost everything below.
The file skeleton
Section titled “The file skeleton”Every page is an .mdx file under src/content/docs/<slug>.mdx. Keep the frontmatter the
page manifest already generated — title,
description, and sidebar.order — and replace the body. Import any component you use on
the line right after the frontmatter:
---title: "My page"description: "One sentence, sentence case."sidebar: order: 3---
Lead with the point. …Import only what you use — an unused import is harmless, but a used-but-unimported component is a hard build error.
Callouts: Asides
Section titled “Callouts: Asides”Callouts are how you surface the gotchas this fleet is full of. Prefer the directive form — it needs no import and reads cleanly in the source. The component form exists for when you need to nest block content or set attributes dynamically; the two render identically.
:::caution[Restart core-mcp after a schema change]core-mcp caches tool schemas in memory. Redeploying the worker updates the DB row,but the changed schema is not picked up until core-mcp restarts.:::<Aside type="caution" title="Restart core-mcp after a schema change">core-mcp caches tool schemas in memory. Redeploying the worker updates the DB row,but the changed schema is not picked up until core-mcp restarts.</Aside>The title in brackets — :::caution[Custom title] — is optional; omit it for the default
label. Pick the type by severity:
| Directive | Component type |
Use it for |
|---|---|---|
:::note |
note |
neutral context the reader needs |
:::tip |
tip |
a shortcut or a recommended path |
:::caution |
caution |
a gotcha that will bite (this fleet has many) |
:::danger |
danger |
data loss, security, or money |
Recipes: Steps
Section titled “Recipes: Steps”Wrap any ordered, do-this-then-that recipe in <Steps> around a numbered list. It renders
the connected-number rail you see in the how-to guides.
<Steps>
1. **Scaffold.** Copy the template repo.
2. **Write the three parts** — input model, output model, `process()`.
3. **Declare pricing** so the tool is billable.
</Steps>Bold the first clause of each step (the imperative) — it becomes the scannable spine of the recipe. Keep prose and code inside the list item so the rail stays unbroken.
Code blocks
Section titled “Code blocks”Code blocks render through Starlight’s built-in Expressive
Code. Always give a language, and add a title="…" when the
block is a real file — the title renders as a filename tab:
```python title="app/tools/my_tool.py"class MyTool(BaseTool[MyInput, MyOutput]): def process(self, input: MyInput, ctx: TaskContext) -> MyOutput: ...```Reach for a fenced block whenever text is $- or brace-heavy — shell, SQL, a
${env}:${namespace}:rest Redis key, a $1/$N placeholder. Those characters are safe
inside a code fence and break the build in bare prose (see below).
Badges
Section titled “Badges”<Badge> is an inline pill. Use it two ways: to tag a language or shape, and — more
importantly — to state a feature’s deploy status.
variant |
Use it for |
|---|---|
note |
neutral / Planned |
tip |
flagship or highlight |
caution |
In code, not deployed |
success |
Deployed |
danger |
broken / removed |
The status-badge convention
Section titled “The status-badge convention”Much of this backend is built but not live. Whenever a page or section’s deploy state matters, say so — an accurate “not deployed yet” is worth more than a confident lie. Use exactly these three:
<Badge text="Deployed" variant="success" /><Badge text="In code, not deployed" variant="caution" /><Badge text="Planned" variant="note" />Rendered inline: Deployed, In code, not deployed, and Planned.
To stamp a badge on the whole page (it appears next to the title and in the sidebar), add it to the frontmatter instead:
sidebar: order: 4 badge: text: In code, not deployed variant: cautionThe MDX traps
Section titled “The MDX traps”MDX parses your Markdown as JSX, so a few plain-text patterns silently break the build.
- Braces and dollars in prose. Bare
{ }and$feed MDX’s expression parser and fail. Anything like{env}:{ns}, a JSON{ "key": … }, or a$Nplaceholder must live inside backticks or a fenced block.${…}inside a code block is fine. - No HTML comments.
{/* … */}is the MDX comment form; the HTML<!-- -->style is rejected. Usually you just want a blank line or a:::note. - Angle brackets in tables. A raw
<Badge … />in a table cell renders the component. To show the literal source, wrap it in backticks:`<Badge text="Deployed" variant="success" />`.
Links and real paths
Section titled “Links and real paths”Two hard rules keep the site’s link graph honest.
-
Internal links are absolute, lower-case slugs with a trailing slash —
/how-to/add-a-tool-worker/, notadd-a-tool-worker.mdor a relative path. Link only to slugs that already exist inscripts/pages.manifest.mjs. The post-buildcheck:linksgate walks every generated page and fails on any internal href that doesn’t resolve. -
Every code/file reference must be a real path, and the best form is a GitHub deep link into the
soundversegitorg:https://github.com/soundversegit/<repo>/blob/staging/<path>. A bare filename in backticks is acceptable when the surrounding prose makes the repo obvious.
The secret rule build-enforced
Section titled “The secret rule ”Write the name and its purpose, and let the deploy plumbing supply the value:
# INTERNAL_RPC_SECRET — shared secret every internal RPC presents; injected by the# deploy engine from the STAGING_/PROD_-prefixed org secret.INTERNAL_RPC_SECRET=${INTERNAL_RPC_SECRET}CORE_DATABASE_GRPC=<core-database-fqdn>:<port>The secret gate enforces this two ways:
- Deny-list. High-signal credential shapes are rejected outright — PEM
PRIVATE KEYblocks, AWS access keys (AKIA…), Anthropic keys (sk-ant-…), OpenAI-style keys (sk-…), GitHub tokens (ghp_…), Slack tokens (xoxb-…), Google keys (AIza…), the prod Postgres host, an Azure SASsig=signature, and JWTs (eyJ…). - Assignment check. Any identifier ending in a secret keyword —
…SECRET,…PASSWORD,…TOKEN,…API_KEY,…PRIVATE_KEY,…CONNECTION_STRING,…SAS— assigned with=to a concrete string is flagged. Assigning it a placeholder passes:<…>,${…},…,xxx,your-…,changeme,placeholder,redacted.
The keyword must be a suffix and the operator must be =, so ordinary prose is safe:
the table name token_ledger, a Mermaid edge label A: token, and the phrase “the
INTERNAL_RPC_SECRET name” never trip it. Only a real …SECRET=<real-value> does.
Diagrams
Section titled “Diagrams”Architecture pages carry Mermaid. Author each as a fenced ```mermaid block; it renders
client-side and re-themes on the light/dark toggle, so keep it theme-neutral and apply the
shared five-tier colour legend. The mechanics live on their own page.
Pre-flight checklist
Section titled “Pre-flight checklist”Before you consider a page done:
-
Frontmatter
title/description/sidebar.orderpreserved; components imported. -
No bare
<word>,{ }, or$in prose; no<!-- -->comments. -
Every internal link is a
/slug/that exists in the manifest; every file reference is a real path (prefer asoundversegitGitHub deep link). -
Deploy-sensitive claims carry the right status badge; facts verified against current
code:sources. -
npm run check:secretsis clean.npm run verify(secrets → build → links) is the full gate — see Running & deploying the docs.
Related
Section titled “Related”- Add a new generation tool worker — the gold-standard page to model
- How these docs are structured — where a new page belongs
- Adding a Mermaid diagram — diagram authoring
- Running & deploying the docs — the local + CI gates
- Environment variable catalog — names-only reference for secrets