Docs Authoring Guide
This is the guide for DataReadyAI engineers writing the Nexa docs. The site is an Astro Starlight project at nexa-docs; all content is MDX under src/content/docs/. Read this before adding or restructuring pages so your change builds cleanly and lands in the right place.
How the site is organized
Section titled “How the site is organized”The site is split into four topics (via the starlight-sidebar-topics plugin), each aimed at a distinct audience. A topic is a top-level directory under src/content/docs/ plus one entry in the starlightSidebarTopics([...]) array in astro.config.mjs.
| Topic | Directory | Audience | Route prefix |
|---|---|---|---|
| Using the Platform | platform/ |
End users of Nexa | /platform/ |
| Deploy & Operate | operate/ |
Customer platform teams installing Nexa | /operate/ |
| Developers & API | developers/ |
Integrators calling the APIs | /developers/ |
| Internal Engineering | internal/ |
DataReadyAI engineers (this topic) | /internal/ |
Each topic’s sidebar groups are declared in astro.config.mjs with autogenerate: { directory: '...' }, so the sidebar mirrors the folder tree. Order within a group comes from each page’s sidebar.order front-matter field; the group label comes from the config, not the folder name.
The Developers topic additionally mounts an auto-generated API reference (starlight-openapi) from the specs in openapi/ — databricks-api.json, snowflake-api.json, and agents-api.json. Do not hand-write API endpoint pages; they come from those specs.
The matrix-absorption rule
Section titled “The matrix-absorption rule”Nexa runs on a 2×2 matrix: AWS or Azure (cloud) crossed with Databricks or Snowflake (data platform). The cardinal rule of this docs set:
Use two reserved syncKey values so a reader’s choice follows them across the whole site (picking “Azure” on one page selects “Azure” everywhere):
nexa-databricks-api.nexa-snowflake-api.Reach for tabs only where the content genuinely differs. If a step is identical on both clouds, write it once as plain prose. Over-tabbing makes pages hard to scan and easy to let drift out of sync.
MDX conventions
Section titled “MDX conventions”Every page is Starlight MDX with YAML front matter. Import any components you use from @astrojs/starlight/components; the vetted set is Tabs, TabItem, Steps, Card, CardGrid, LinkCard, LinkButton, Aside, Badge, FileTree, and Code. Asides can also be written as :::note, :::tip, :::caution, and :::danger directives with no import.
- Front matter: keep
titleand a specific one-sentencedescription(it is what/llms.txtand search index on). Preserve any existingsidebar:block. - Headings:
##and###only — they build the page’s on-page table of contents. One concept per##. - Structured facts (fields, ports, options, env vars) go in tables or ordered lists, not prose, so they survive extraction into plain text.
- MDX escaping: a raw
<or{in prose is parsed as JSX. Write “less than” or wrap the value in backticks. Any<Something>that is not a real imported component must be inside a code span. - Procedures: wrap ordered steps in
<Steps>; put commands in fenced code blocks with a language tag so they are copy-pasteable.
Internal links
Section titled “Internal links”Links between docs pages must be root-absolute with a trailing slash, for example [Connectors](/platform/connectors/overview/). The build runs starlight-links-validator, which fails on any link to a route that does not exist — a broken internal link breaks the build, it is not a warning.
Links into the auto-generated API reference under /developers/api/... are allowed and are excluded from the validator (those routes are injected at build time and the validator cannot see them in the content collection). When you are unsure a target exists, omit the link rather than guess.
Adding a page
Section titled “Adding a page”-
Create the MDX file in the correct topic directory. The route is the path under
src/content/docs/minus the extension —internal/runbooks/common-runbooks.mdxserves at/internal/runbooks/common-runbooks/. -
Add front matter with
title, a self-describingdescription, andsidebar.orderto position it within its group:---title: "My New Runbook"description: "One sentence stating what this page covers and for whom."sidebar:order: 3--- -
Write the body. Lead with 1–2 sentences of standalone context, then the mechanism. Absorb any cloud/warehouse variants into synced tabs.
-
Run the build locally (below) and fix any link-validation errors before opening a PR.
You do not need to touch astro.config.mjs to add a page inside an existing group — the sidebar autogenerates from the directory. Only edit the config to add a whole new group or topic.
Build and link validation
Section titled “Build and link validation”Directorynexa-docs/
- astro.config.mjs topics, OpenAPI mounts, plugins
Directoryopenapi/ API specs → generated reference
- …
Directorysrc/
Directorycontent/docs/ all MDX pages
- …
- styles/global.css brand overrides
- package.json
Local development and the build:
npm installnpm run dev # live preview at http://localhost:4321npm run build # production build — runs link validationnpm run preview # serve the built dist/npm run build is the gate. It fails on:
- A broken root-absolute internal link (
starlight-links-validator). - Invalid MDX — an unescaped
<or{, or a<Component>that was not imported.
The build also emits /llms.txt and /llms-full.txt (via starlight-llms-txt), which is why every page needs a clean heading hierarchy and a specific description. The site is served as a static bundle from an Nginx container (Dockerfile + nginx.conf at the repo root) at https://docs.nexa-drai.com.