"tests/vscode:/vscode.git/clone" did not exist on "36c260dad604ccc845150753f2530b5b2ba9d7e6"
Unverified Commit 817f2eeb authored by dagil-nvidia's avatar dagil-nvidia Committed by GitHub
Browse files

docs: add Dynamo Docs Guide and Claude Code skills (#6684)


Signed-off-by: default avatarDan Gil <dagil@nvidia.com>
Co-authored-by: default avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 1bde94d4
---
name: add-dynamo-docs
description: Add a new page to the Dynamo Fern docs site. Use when creating new documentation pages.
---
# Add a Dynamo Docs Page
Claude Code skill for adding a new page to the Dynamo Fern documentation site.
## Related Skills
| Skill | Use When |
|-------|----------|
| [rm-dynamo-docs](../rm-dynamo-docs/SKILL.md) | Removing an existing docs page |
| [update-dynamo-docs](../update-dynamo-docs/SKILL.md) | Editing an existing docs page |
---
## Branch Rule
**ALL edits happen on `main` (or a feature branch based on `main`).**
The `docs-website` branch is CI-managed and must **never** be edited by hand.
## Working Directory
Must be in the `dynamo` repo (not `dynamo-tpm`). Architecture details: `docs/README.md`.
## When Invoked
### 1. Gather Information
Ask for:
- **Page title** — appears in the sidebar and as the H1
- **Target section** — which sidebar section (e.g., `Getting Started`, `User Guides`, `Components`)
- **Filename** — kebab-case `.md` file (e.g., `my-new-feature.md`)
- **Subdirectory** — which `docs/pages/` subdirectory (e.g., `getting-started`, `features`, `components`)
### 2. Create the Page
Create `docs/pages/<subdirectory>/<filename>.md` with SPDX header and Fern frontmatter:
```markdown
---
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
title: <Page Title>
---
# <Page Title>
<!-- Content goes here -->
```
### 3. Add Navigation Entry
Edit `docs/versions/dev.yml` and add the page under the correct section:
```yaml
- page: <Page Title>
path: ../pages/<subdirectory>/<filename>.md
```
**Section locations in `dev.yml`** (search for the comment banner):
- `# ==================== Getting Started ====================`
- `# ==================== Kubernetes Deployment ====================`
- `# ==================== User Guides ====================`
- `# ==================== Backends ====================`
- `# ==================== Components ====================`
- `# ==================== Integrations ====================`
- `# ==================== Documentation ====================`
- `# ==================== Design Docs ====================`
- `# ==================== Blog ====================`
- `# ==================== Hidden Pages ====================`
### 4. Write Content
Use standard **GitHub-flavored markdown**. For callouts, use GitHub's native syntax — CI auto-converts to Fern format:
```markdown
> [!NOTE]
> Helpful context for the reader.
> [!WARNING]
> Something the reader should be careful about.
> [!TIP]
> A useful suggestion.
```
**Callout mapping** (GitHub → Fern):
| GitHub Syntax | Fern Component |
|---|---|
| `> [!NOTE]` | `<Note>` |
| `> [!TIP]` | `<Tip>` |
| `> [!IMPORTANT]` | `<Info>` |
| `> [!WARNING]` | `<Warning>` |
| `> [!CAUTION]` | `<Error>` |
Reference images from `docs/assets/`:
```markdown
![Diagram](../assets/my-diagram.png)
```
### 5. Validate
```bash
cd docs
ln -sf . fern # symlink required by Fern CLI
fern check
fern docs broken-links
```
### 6. Preview Locally (Optional)
```bash
cd docs
fern docs dev
```
Opens a local preview at `http://localhost:3000` with hot reload. No token required.
### 7. Commit
```bash
git add docs/pages/<subdirectory>/<filename>.md docs/versions/dev.yml
git commit -s -m "docs: add <page-title> page"
```
## Debugging
### `fern check` fails
- **Invalid YAML in `dev.yml`:** Check indentation — nav entries use 2-space indent. A `- page:` must be inside a `contents:` block.
- **Missing file:** The `path:` in `dev.yml` must match the actual file location. Paths are relative to `docs/versions/` (e.g., `../pages/getting-started/quickstart.md`).
### `fern docs broken-links` reports errors
- **Broken internal link:** A markdown link reference points to a file that doesn't exist. Fix the path or remove the link.
- **Anchor not found:** A `#section-heading` link doesn't match any heading in the target page.
### CI fails after merge
- **MDX parse error:** Angle-bracket URLs like `<https://example.com>` break MDX parsing. Use `[text](https://example.com)` instead.
- **Broken links check:** The `detect_broken_links.py` job checks relative links across all docs. If your new page links to a file that doesn't exist yet, CI will fail.
- **Fern publish error:** Check the Actions tab for the `Fern Docs` workflow. Common causes: expired `FERN_TOKEN`, invalid `docs.yml` syntax, or a file referenced in `dev.yml` that wasn't synced to `docs-website`.
### Page doesn't appear on the live site
- **Missing nav entry:** The page exists but isn't in `docs/versions/dev.yml`. Add it.
- **Hidden section:** The page is inside a `hidden: true` section. It's accessible by direct URL but won't appear in the sidebar.
- **Sync delay:** After merge to `main`, the sync-dev workflow takes a few minutes to publish.
## Key References
| File | Purpose |
|------|---------|
| `docs/versions/dev.yml` | Navigation tree — add entries here |
| `docs/pages/` | Content directory — create pages here |
| `docs/assets/` | Images, SVGs, fonts |
| `docs/convert_callouts.py` | Callout conversion rules (GitHub → Fern) |
| `docs/README.md` | Full architecture guide |
---
name: rm-dynamo-docs
description: Remove a page from the Dynamo Fern docs site. Use when deleting documentation pages.
---
# Remove a Dynamo Docs Page
Claude Code skill for removing a page from the Dynamo Fern documentation site.
## Related Skills
| Skill | Use When |
|-------|----------|
| [add-dynamo-docs](../add-dynamo-docs/SKILL.md) | Adding a new docs page |
| [update-dynamo-docs](../update-dynamo-docs/SKILL.md) | Editing an existing docs page |
---
## Branch Rule
**ALL edits happen on `main` (or a feature branch based on `main`).**
The `docs-website` branch is CI-managed and must **never** be edited by hand.
## Working Directory
Must be in the `dynamo` repo (not `dynamo-tpm`). Architecture details: `docs/README.md`.
## When Invoked
### 1. Identify the Page
Ask for the page to remove (accepts any of):
- File path (e.g., `docs/pages/guides/old-page.md`)
- Page title (e.g., "Old Page")
- Topic keyword to search for
If given a title or keyword, search for the page:
```bash
# Search by title in navigation
grep -n "<title>" docs/versions/dev.yml
# Search by keyword in content
grep -rl "<keyword>" docs/pages/
```
### 2. Find the Navigation Entry
Locate the page's entry in `docs/versions/dev.yml`:
```bash
grep -n "<filename>" docs/versions/dev.yml
```
Note the exact `- page:` block and its indentation level. If the page is the
sole entry in a `- section:` block, the entire section should be removed.
### 3. Check for Incoming Links
Search for references to this page from other docs:
```bash
# Search for the filename across all docs pages
grep -r "<filename>" docs/pages/ --include="*.md"
# Also check the navigation file for any cross-references
grep -r "<filename>" docs/versions/
```
Report any files that link to the page being removed — these links will break
and need updating.
### 4. Remove the Markdown File
```bash
git rm docs/pages/<subdirectory>/<filename>.md
```
### 5. Remove the Navigation Entry
Edit `docs/versions/dev.yml` and delete the `- page:` block (and its `path:`
line). If this was the last page in a section, remove the entire `- section:`
block.
### 6. Fix Broken Incoming Links
For each file that linked to the removed page:
- Remove the link, or
- Redirect to a replacement page, or
- Leave a note about the removal
### 7. Validate
```bash
cd docs
ln -sf . fern # symlink required by Fern CLI
fern check
fern docs broken-links
```
### 8. Preview Locally (Optional)
```bash
cd docs
fern docs dev
```
Opens a local preview at `http://localhost:3000` with hot reload. No token required.
### 9. Commit
```bash
git add -u docs/
git commit -s -m "docs: remove <page-title> page"
```
## Debugging
### `fern check` fails
- **Orphaned nav entry:** You deleted the file but left the `- page:` entry in `dev.yml`. Remove it.
- **Empty section:** If the removed page was the only entry in a section, delete the entire `- section:` block from `dev.yml`.
### `fern docs broken-links` reports errors
- **Incoming links to removed page:** Other pages still link to the deleted file. Search with `grep -r "<filename>" docs/pages/` and update or remove those links.
### CI fails after merge
- **MDX parse error:** Angle-bracket URLs like `<https://example.com>` break MDX parsing. Use `[text](https://example.com)` instead.
- **Broken links check:** The `detect_broken_links.py` job found pages that still reference the removed file. Fix all incoming links before merging.
- **Fern publish error:** Check the Actions tab for the `Fern Docs` workflow. Common causes: expired `FERN_TOKEN`, invalid `docs.yml` syntax.
### Page still appears on the live site
- **Sync delay:** After merge to `main`, the sync-dev workflow takes a few minutes to publish.
- **Cached version:** Fern CDN may cache the old page briefly. Hard-refresh or wait a few minutes.
## Key References
| File | Purpose |
|------|---------|
| `docs/versions/dev.yml` | Navigation tree — remove entries here |
| `docs/pages/` | Content directory — delete pages here |
| `docs/README.md` | Full architecture guide |
---
name: update-dynamo-docs
description: Update an existing page in the Dynamo Fern docs site. Use when editing content, titles, or moving pages between sections.
---
# Update a Dynamo Docs Page
Claude Code skill for updating an existing page in the Dynamo Fern documentation site.
## Related Skills
| Skill | Use When |
|-------|----------|
| [add-dynamo-docs](../add-dynamo-docs/SKILL.md) | Adding a new docs page |
| [rm-dynamo-docs](../rm-dynamo-docs/SKILL.md) | Removing an existing docs page |
---
## Branch Rule
**ALL edits happen on `main` (or a feature branch based on `main`).**
The `docs-website` branch is CI-managed and must **never** be edited by hand.
## Working Directory
Must be in the `dynamo` repo (not `dynamo-tpm`). Architecture details: `docs/README.md`.
## When Invoked
### 1. Locate the Page
Ask for the page to update (accepts any of):
- File path (e.g., `docs/pages/guides/quickstart.md`)
- Page title (e.g., "Quickstart")
- Topic keyword to search for
If given a title or keyword, find the page:
```bash
# Search by title in navigation
grep -n "<title>" docs/versions/dev.yml
# Search by keyword in content
grep -rl "<keyword>" docs/pages/
```
### 2. Read Current Content
Read the page and its navigation entry:
- The markdown file in `docs/pages/`
- The corresponding entry in `docs/versions/dev.yml`
Note the current:
- **Title** (from frontmatter `title:` field)
- **Section** (which sidebar section it belongs to)
- **Path** (relative path in `dev.yml`)
### 3. Apply Edits
Handle three types of changes:
#### Content Only
Edit the markdown file directly. No navigation changes needed.
#### Title Change
1. Update the `title:` field in the markdown frontmatter
2. Update the `- page:` display name in `docs/versions/dev.yml`
#### Section Move
1. Move the markdown file to the new subdirectory:
```bash
git mv docs/pages/<old-subdir>/<file>.md docs/pages/<new-subdir>/<file>.md
```
2. Remove the old `- page:` entry from `dev.yml`
3. Add a new `- page:` entry under the target section in `dev.yml`
4. Update the `path:` to reflect the new location
### 4. Check Incoming Links (If Path Changed)
If the file was moved, search for references that need updating:
```bash
# Search for the old path across all docs
grep -r "<old-filename>" docs/pages/ --include="*.md"
grep -r "<old-filename>" docs/versions/
```
Update all references to point to the new path.
### 5. Content Guidelines
Use standard **GitHub-flavored markdown**. For callouts, use GitHub's native syntax — CI auto-converts to Fern format:
```markdown
> [!NOTE]
> Helpful context for the reader.
> [!WARNING]
> Something the reader should be careful about.
```
**Callout mapping** (GitHub → Fern):
| GitHub Syntax | Fern Component |
|---|---|
| `> [!NOTE]` | `<Note>` |
| `> [!TIP]` | `<Tip>` |
| `> [!IMPORTANT]` | `<Info>` |
| `> [!WARNING]` | `<Warning>` |
| `> [!CAUTION]` | `<Error>` |
### 6. Validate
```bash
cd docs
ln -sf . fern # symlink required by Fern CLI
fern check
fern docs broken-links
```
### 7. Preview Locally (Optional)
```bash
cd docs
fern docs dev
```
Opens a local preview at `http://localhost:3000` with hot reload. No token required.
### 8. Commit
```bash
git add docs/pages/ docs/versions/dev.yml
git commit -s -m "docs: update <page-title>"
```
## Debugging
### `fern check` fails
- **Invalid YAML in `dev.yml`:** Check indentation — nav entries use 2-space indent. A `- page:` must be inside a `contents:` block.
- **Missing file:** If you moved a page, the `path:` in `dev.yml` must match the new location.
- **Duplicate entry:** The same page appears twice in `dev.yml`. Remove the old entry after a section move.
### `fern docs broken-links` reports errors
- **Stale internal links:** After moving or renaming a page, other pages may still link to the old path. Search with `grep -r "<old-filename>" docs/pages/` and update references.
- **Anchor not found:** A `#section-heading` link doesn't match any heading in the target page. Check if the heading text changed.
### CI fails after merge
- **MDX parse error:** Angle-bracket URLs like `<https://example.com>` break MDX parsing. Use `[text](https://example.com)` instead.
- **Broken links check:** The `detect_broken_links.py` job found stale references to the old path. Fix all incoming links before merging.
- **Fern publish error:** Check the Actions tab for the `Fern Docs` workflow. Common causes: expired `FERN_TOKEN`, invalid `docs.yml` syntax, or a moved file that wasn't synced to `docs-website`.
### Changes don't appear on the live site
- **Title mismatch:** You updated the frontmatter `title:` but not the `- page:` name in `dev.yml` (or vice versa). Keep them in sync.
- **Sync delay:** After merge to `main`, the sync-dev workflow takes a few minutes to publish.
## Key References
| File | Purpose |
|------|---------|
| `docs/versions/dev.yml` | Navigation tree — update entries here if title/path changes |
| `docs/pages/` | Content directory — edit pages here |
| `docs/assets/` | Images, SVGs, fonts |
| `docs/convert_callouts.py` | Callout conversion rules (GitHub → Fern) |
| `docs/README.md` | Full architecture guide |
...@@ -196,6 +196,11 @@ jobs: ...@@ -196,6 +196,11 @@ jobs:
echo "Syncing fern.config.json to docs-website branch..." echo "Syncing fern.config.json to docs-website branch..."
cp source-checkout/docs/fern.config.json docs-checkout/fern/fern.config.json cp source-checkout/docs/fern.config.json docs-checkout/fern/fern.config.json
# Sync docs/README.md (developer guide, referenced from dev.yml)
if [ -f source-checkout/docs/README.md ]; then
cp source-checkout/docs/README.md docs-checkout/fern/README.md
fi
# Sync .gitignore if it exists # Sync .gitignore if it exists
if [ -f source-checkout/docs/.gitignore ]; then if [ -f source-checkout/docs/.gitignore ]; then
cp source-checkout/docs/.gitignore docs-checkout/fern/.gitignore cp source-checkout/docs/.gitignore docs-checkout/fern/.gitignore
......
---
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
sidebar-title: Dynamo Docs Guide
---
# How to Build and Publish Dynamo Docs
This document describes the architecture, workflows, and maintenance procedures for the
NVIDIA Dynamo documentation website powered by [Fern](https://buildwithfern.com).
<Note>
The documentation website is hosted entirely on
[Fern](https://buildwithfern.com). CI publishes to
`dynamo.docs.buildwithfern.com`; the production domain
`docs.dynamo.nvidia.com` is a custom domain alias that points to the
Fern-hosted site. There is no separate server — Fern handles hosting,
CDN, and versioned URL routing.
</Note>
<Error>
The `docs-website` branch is **CI-managed and must never be edited by
hand**. All documentation authoring happens on `main` (or a feature
branch based on `main`). The sync workflow copies changes to
`docs-website` automatically.
</Error>
---
## Table of Contents
- [Branch Architecture](#branch-architecture)
- [Directory Layout](#directory-layout)
- [Configuration Files](#configuration-files)
- [GitHub Workflows](#github-workflows)
- [Fern Docs Workflow](#fern-docs-workflow-fern-docsyml)
- [Docs Link Check Workflow](#docs-link-check-workflow-docs-link-checkyml)
- [Content Authoring](#content-authoring)
- [Callout Conversion](#callout-conversion)
- [Running Locally](#running-locally)
- [Version Management](#version-management)
- [How Publishing Works](#how-publishing-works)
- [Common Tasks](#common-tasks)
- [Claude Code Skills](#claude-code-skills)
---
## Claude Code Skills
Three Claude Code skills automate common docs tasks. Invoke them as slash
commands in Claude Code (e.g., `/add-dynamo-docs`) — each skill walks through
the full workflow: creating or editing the markdown file, updating the
navigation in `docs/versions/dev.yml`, and running `fern check` to validate.
| Skill | Description |
|-------|-------------|
| [add-dynamo-docs](/.claude/skills/add-dynamo-docs/SKILL.md) | Add a new page — creates the file with frontmatter, adds the nav entry |
| [rm-dynamo-docs](/.claude/skills/rm-dynamo-docs/SKILL.md) | Remove a page — deletes the file, removes the nav entry, checks for broken links |
| [update-dynamo-docs](/.claude/skills/update-dynamo-docs/SKILL.md) | Update a page — edit content, rename, or move between sections |
---
## Branch Architecture
The documentation system uses a **dual-branch model**:
| Branch | Purpose | Docs directory |
|---|---|---|
| `main` | Source of truth for **dev** (unreleased) documentation | `docs/` |
| `docs-website` | Published documentation including **all versioned snapshots** | `docs/` |
Authors edit pages on `main`. A GitHub Actions workflow automatically syncs
changes to the `docs-website` branch and publishes them to Fern. The
`docs-website` branch is never edited by hand — it is entirely managed by CI.
### Why two branches?
The `docs-website` branch accumulates versioned snapshots over time (e.g.
`pages-v0.8.0/`, `pages-v0.8.1/`). Keeping these on a separate branch avoids
bloating the `main` branch with frozen copies of old documentation.
---
## Directory Layout
### On `main`
```text
docs/
├── fern.config.json # Fern org + CLI version pin
├── docs.yml # Site configuration (instances, branding, layout)
├── versions/
│ └── dev.yml # Navigation tree for the dev version
├── pages/ # Markdown content (the actual docs)
│ ├── getting-started/
│ ├── guides/
│ ├── kubernetes/
│ ├── reference/
│ └── ...
├── assets/ # Images, fonts, SVGs, logos
├── components/
│ └── CustomFooter.tsx # React component for the site footer
├── main.css # Custom CSS (NVIDIA branding, dark mode, etc.)
├── convert_callouts.py # GitHub → Fern admonition converter script
└── diagrams/ # D2 diagram source files
```
### On `docs-website`
The `docs-website` branch mirrors the above structure, plus versioned snapshots:
```text
docs/
├── docs.yml # Includes the full versions array
├── versions/
│ ├── dev.yml # "Next" / dev navigation (synced from main)
│ ├── v0.8.1.yml # Navigation for v0.8.1 snapshot
│ └── v0.8.0.yml # Navigation for v0.8.0 snapshot
├── pages/ # Current dev content (synced from main)
├── pages-v0.8.1/ # Frozen snapshot of pages/ at v0.8.1
├── pages-v0.8.0/ # Frozen snapshot of pages/ at v0.8.0
└── ... # (other files same as main)
```
Each `pages-vX.Y.Z/` directory is an immutable copy of `pages/` taken at
release time. The corresponding `versions/vX.Y.Z.yml` file is a copy of
`dev.yml` with all `../pages/` paths rewritten to `../pages-vX.Y.Z/`.
---
## Configuration Files
### `fern.config.json`
```json
{
"organization": "nvidia",
"version": "3.73.0"
}
```
- **organization**: The Fern organization that owns the docs site.
- **version**: Pins the Fern CLI version used for generation.
### `docs.yml`
This is the main Fern site configuration. Key sections:
| Section | Purpose |
|---|---|
| `instances` | Deployment targets — staging URL and custom production domain |
| `products` | Defines the product ("Dynamo") and its version list |
| `navbar-links` | GitHub repo link in the navigation bar |
| `footer` | Points to `CustomFooter.tsx` React component |
| `layout` | Page width, sidebar width, searchbar placement, etc. |
| `colors` | NVIDIA green (`#76B900`) accent, black/white backgrounds |
| `typography` | NVIDIA Sans body font, Roboto Mono code font |
| `logo` | NVIDIA logos (dark + light variants), 20px height |
| `js` | Adobe Analytics script injection |
| `css` | Custom `main.css` stylesheet |
**Important:** On `main`, `docs.yml` only lists the `dev` version. On
`docs-website`, it contains the **full versions array** (dev + all releases).
The sync workflow preserves the versions array from `docs-website` when copying
`docs.yml` from `main`.
### `versions/dev.yml`
Defines the navigation tree — the sidebar structure of the docs site. Each
entry maps a page title to a markdown file path:
```yaml
navigation:
- section: Getting Started
contents:
- page: Quickstart
path: ../pages/getting-started/quickstart.md
- page: Support Matrix
path: ../pages/reference/support-matrix.md
```
Sections can be nested. Pages can be marked as `hidden: true` to make them
accessible by URL but invisible in the sidebar.
---
## GitHub Workflows
### Fern Docs Workflow (`fern-docs.yml`)
**Location:** `.github/workflows/fern-docs.yml`
This single consolidated workflow handles linting, syncing, versioning, and
publishing. It runs three jobs depending on the trigger:
#### Job 1: Lint (PRs)
**Triggers:** Pull requests that modify `docs/**` files.
**Steps:**
1. `fern check` — validates Fern configuration syntax
2. `fern docs broken-links` — checks for broken internal links
**Purpose:** Catches broken docs before they merge.
#### Job 2: Sync dev (push to `main`)
**Triggers:** Push to `main` that modifies `docs/**` files, or manual
`workflow_dispatch` (with no tag specified).
**Steps:**
1. Checks out both `main` and `docs-website` branches side-by-side
2. Copies from `main``docs-website`:
- `docs/pages/` — all markdown content
- `docs/versions/dev.yml` — navigation structure
- `docs/assets/` — images, fonts, SVGs
- `docs/fern.config.json` — Fern config
- `docs/components/` — React components
- `docs/main.css` — custom styles
- `docs/convert_callouts.py` — conversion script
3. Runs `convert_callouts.py` to transform GitHub-style callouts to Fern format
4. Updates `docs.yml` from `main` **while preserving the versions array** from
`docs-website` (uses `yq` to save/restore the versions list)
5. Commits and pushes to `docs-website`
6. Publishes to Fern via `fern generate --docs`
**Symlink trick:** The Fern CLI expects a `fern/` directory. Since docs live in
`docs/`, the workflow creates a symlink `docs/fern → docs/.` (i.e., pointing to
itself) so Fern can find its config files.
#### Job 3: Version Release (tags)
**Triggers:** New Git tags matching `vX.Y.Z` (e.g., `v0.9.0`, `v1.0.0`), or
manual `workflow_dispatch` with a tag specified.
**Steps:**
1. Validates tag format (must be exactly `vX.Y.Z`, no suffixes like `-rc1`)
2. Checks that the version doesn't already exist (no duplicate snapshots)
3. Creates `docs/pages-vX.Y.Z/` by copying `docs/pages/`
4. Rewrites GitHub links in the snapshot:
- `github.com/ai-dynamo/dynamo/tree/main``tree/vX.Y.Z`
- `github.com/ai-dynamo/dynamo/blob/main``blob/vX.Y.Z`
5. Runs `convert_callouts.py` on the snapshot
6. Creates `docs/versions/vX.Y.Z.yml` from `dev.yml` with paths updated to
`../pages-vX.Y.Z/`
7. Updates `docs.yml`:
- Inserts new version right after the "dev" entry
- Sets the product's default `path` to the new version
- Updates the "Latest" display-name to `"Latest (vX.Y.Z)"`
8. Commits and pushes to `docs-website`
9. Publishes to Fern via `fern generate --docs`
**Anti-recursion note:** Pushes made with `GITHUB_TOKEN` do not trigger other
workflows (GitHub's built-in guard). This is why the publish step is inline in
each job rather than in a separate workflow.
### Docs Link Check Workflow (`docs-link-check.yml`)
**Location:** `.github/workflows/docs-link-check.yml`
**Triggers:** Push to `main` and pull requests.
Runs two independent link-checking jobs:
| Job | Tool | What it checks |
|---|---|---|
| `lychee` | [Lychee](https://lychee.cli.rs/) | External HTTP links (with caching, retries, rate-limit handling). Runs offline for PRs. |
| `broken-links-check` | Custom Python script (`detect_broken_links.py`) | Internal relative markdown links and symlinks. Creates GitHub annotations on PRs pointing to exact lines with broken links. |
---
## Content Authoring
### Writing docs on `main`
1. Edit or add markdown files in `docs/pages/`.
2. If adding a new page, add an entry in `docs/versions/dev.yml` to make it
appear in the sidebar navigation.
3. Use standard GitHub-flavored markdown. Callouts (admonitions) should use
GitHub's native syntax — they are automatically converted during sync:
```markdown
> [!NOTE]
> This is a note that will become a Fern `<Note>` component.
> [!WARNING]
> This warning will become a Fern `<Warning>` component.
```
4. Open a PR. The lint jobs (`fern check`, `fern docs broken-links`, lychee,
broken-links-check) run automatically.
5. Once merged to `main`, the sync-dev workflow publishes changes within minutes.
### Assets and images
Place images in `docs/assets/` and reference them with relative paths from your
markdown files:
```markdown
![Architecture diagram](../assets/architecture.png)
```
### Custom components
React components in `docs/components/` can be used in markdown via MDX. The
`CustomFooter.tsx` renders the NVIDIA footer with legal links and branding.
---
## Callout Conversion
The `docs/convert_callouts.py` script bridges the gap between GitHub-flavored
markdown and Fern's admonition format. This lets authors use GitHub's native
callout syntax on `main` while Fern gets its required component format.
### Mapping
| GitHub Syntax | Fern Component |
|---|---|
| `> [!NOTE]` | `<Note>` |
| `> [!TIP]` | `<Tip>` |
| `> [!IMPORTANT]` | `<Info>` |
| `> [!WARNING]` | `<Warning>` |
| `> [!CAUTION]` | `<Error>` |
### Usage
```bash
# Convert all files in a directory (recursive, in-place)
python convert_callouts.py --dir docs/pages
# Convert a single file
python convert_callouts.py input.md output.md
# Run built-in tests
python convert_callouts.py --test
```
The conversion happens automatically during the sync-dev and release-version
workflows. Authors never need to run it manually.
---
## Running Locally
You can preview the documentation site on your machine using the
[Fern CLI](https://buildwithfern.com/learn/cli-api/overview). This is useful
for verifying layout, navigation, and content before opening a PR.
### Prerequisites
Install the Fern CLI globally via npm:
```bash
npm install -g fern-api
```
### Create the `fern` symlink
The Fern CLI requires its configuration files to live inside a directory called
`fern/`. In this repo the docs live in `docs/`, so you need to create a symlink
that points `fern` back to the same directory:
```bash
cd docs
ln -s . fern
```
This makes the CLI find `fern/fern.config.json`, `fern/docs.yml`, etc. without
moving any files. The symlink is listed in `.gitignore` and should not be
committed.
### Validate configuration
Run `fern check` to validate that `docs.yml`, `fern.config.json`, and the
navigation files are syntactically correct:
```bash
cd docs
fern check
```
### Check for broken links
Use `fern docs broken-links` to scan all pages for internal links that don't
resolve:
```bash
cd docs
fern docs broken-links
```
This is the same check that runs in CI on every pull request.
### Start a local preview server
Run `fern docs dev` to build the site and serve it locally with hot-reload:
```bash
cd docs
fern docs dev
```
The local server lets you see exactly how pages will look on the live site,
including navigation, version dropdowns, and custom styling.
---
## Version Management
### How versions work
The Fern site supports a version dropdown in the UI. Each version is defined by:
1. **A navigation file** (`docs/versions/vX.Y.Z.yml`) — sidebar structure
pointing to version-specific pages.
2. **A pages directory** (`docs/pages-vX.Y.Z/`) — frozen snapshot of the
markdown content at release time.
3. **An entry in `docs.yml`** — tells Fern about the version's display name,
slug, and config path.
### Version types
| Version | Display Name | Slug | Description |
|---|---|---|---|
| Latest | `Latest (vX.Y.Z)` | `/` | Default version; points to the newest release |
| Stable releases | `vX.Y.Z` | `vX.Y.Z` | Immutable snapshots |
| Dev | `dev` | `dev` | Tracks `main`; updated on every push |
### URL structure
- **Latest (default):** `docs.dynamo.nvidia.com/dynamo/`
- **Specific version:** `docs.dynamo.nvidia.com/dynamo/v0.8.1/`
- **Dev:** `docs.dynamo.nvidia.com/dynamo/dev/`
### Creating a new version
Simply push a semver tag:
```bash
git tag v0.9.0
git push origin v0.9.0
```
The `release-version` job in `fern-docs.yml` handles everything else
automatically.
---
## How Publishing Works
```text
┌─────────────────────────────────────────────────────────────────────┐
│ CONTINUOUS (dev) │
│ │
│ Developer pushes to main │
│ │ │
│ ▼ │
│ docs/** changed? ── No ──▶ (nothing happens) │
│ │ │
│ Yes │
│ │ │
│ ▼ │
│ sync-dev job: │
│ 1. Copy docs/pages/, assets/, configs → docs-website branch │
│ 2. Convert GitHub callouts → Fern admonitions │
│ 3. Preserve version list from docs-website's docs.yml │
│ 4. Commit + push to docs-website │
│ 5. fern generate --docs (publishes to Fern) │
│ │ │
│ ▼ │
│ Live on docs.dynamo.nvidia.com/dynamo/dev/ within minutes │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ VERSION RELEASE │
│ │
│ Maintainer pushes vX.Y.Z tag │
│ │ │
│ ▼ │
│ release-version job: │
│ 1. Validate tag format (vX.Y.Z only) │
│ 2. Check version doesn't already exist │
│ 3. Snapshot pages/ → pages-vX.Y.Z/ │
│ 4. Rewrite GitHub links (tree/main → tree/vX.Y.Z) │
│ 5. Convert callouts in snapshot │
│ 6. Create versions/vX.Y.Z.yml (paths → pages-vX.Y.Z/) │
│ 7. Update docs.yml (insert version, set as default) │
│ 8. Commit + push to docs-website │
│ 9. fern generate --docs (publishes to Fern) │
│ │ │
│ ▼ │
│ New version visible in dropdown at docs.dynamo.nvidia.com/dynamo/ │
└─────────────────────────────────────────────────────────────────────┘
```
### Secrets
| Secret | Purpose |
|---|---|
| `FERN_TOKEN` | Authentication token for `fern generate --docs`. Required for publishing. Stored in GitHub repo secrets. |
---
## Common Tasks
### Update existing documentation
1. Edit files in `docs/pages/` on a feature branch.
2. If adding a new page, add its entry in `docs/versions/dev.yml`.
3. Open a PR — linting runs automatically.
4. Merge — sync + publish happens automatically.
### Add a new top-level section
1. Create a directory under `docs/pages/` (e.g., `docs/pages/new-section/`).
2. Add markdown files for each page.
3. Add a new `- section:` block in `docs/versions/dev.yml` with the desired
hierarchy.
### Release versioned documentation
```bash
git tag v1.0.0
git push origin v1.0.0
```
That's it. The workflow snapshots the current dev docs, creates the version
config, and publishes.
### Manually trigger a sync or release
Go to **Actions → Fern Docs → Run workflow**:
- Leave **tag** empty to trigger a dev sync.
- Enter a tag (e.g., `v0.9.0`) to trigger a version release.
### Debug a failed publish
1. Check the **Actions** tab for the failed `Fern Docs` workflow run.
2. Common issues:
- **Broken links:** Fix the links flagged by `fern docs broken-links`.
- **Invalid YAML:** Check `docs.yml` or `versions/dev.yml` syntax.
- **Expired `FERN_TOKEN`:** Rotate the token in repo secrets.
- **Duplicate version:** The tag was already released; check `docs-website`
for existing `pages-vX.Y.Z/` directory.
---
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
title: Building Documentation
---
This directory contains the documentation source files for NVIDIA Dynamo.
## Prerequisites
- Python 3.11 or later
- [uv](https://docs.astral.sh/uv/) package manager
## Build Instructions
### Option 1: Dedicated Docs Environment (Recommended)
This approach builds the docs without requiring the full project dependencies (including `ai-dynamo-runtime`):
```bash
# One-time setup: Create docs environment and install dependencies
uv venv .venv-docs
uv pip install --python .venv-docs --group docs
# Generate documentation
uv run --python .venv-docs --no-project docs/generate_docs.py
```
The generated HTML will be available in `docs/build/html/`.
### Option 2: Using Full Development Environment
If you already have the full project dependencies installed (i.e., you're actively developing the codebase), you can use `uv run` directly:
```bash
uv run --group docs docs/generate_docs.py
```
This will use your existing project environment and add the docs dependencies.
### Option 3: Using Docker
Build the docs in a Docker container with all dependencies isolated:
```bash
docker build -f container/Dockerfile.docs -t dynamo-docs .
```
The documentation will be built inside the container. To extract the built docs:
```bash
# Run the container and copy the output
docker run --rm -v $(pwd)/docs/build:/workspace/dynamo/docs/build dynamo-docs
# Or create a container to copy files from
docker create --name temp-docs dynamo-docs
docker cp temp-docs:/workspace/dynamo/docs/build ./docs/build
docker rm temp-docs
```
This approach is ideal for CI/CD pipelines or when you want complete isolation from your local environment.
## Directory Structure
- `docs/` - Documentation source files (Markdown and reStructuredText)
- `docs/conf.py` - Sphinx configuration
- `docs/_static/` - Static assets (CSS, JS, images)
- `docs/_extensions/` - Custom Sphinx extensions
- `docs/build/` - Generated documentation output (not tracked in git)
## Redirect Creation
When moving or renaming files a redirect must be created.
Redirect entries should be added to the `redirects` dictionary in `conf.py`. For detailed information on redirect syntax, see the [sphinx-reredirects usage documentation](https://documatt.com/sphinx-reredirects/usage/#introduction).
## Dependency Management
Documentation dependencies are defined in `pyproject.toml` under the `[dependency-groups]` section:
```toml
[dependency-groups]
docs = [
"sphinx>=8.1",
"nvidia-sphinx-theme>=0.0.8",
# ... other doc dependencies
]
```
## Troubleshooting
### Build Warnings
The build process treats warnings as errors. Common issues:
- **Missing toctree entries**: Documents must be referenced in a table of contents
- **Non-consecutive headers**: Don't skip header levels (e.g., H1 → H3)
- **Broken links**: Ensure all internal and external links are valid
### Missing Dependencies
If you encounter import errors, ensure the docs dependencies are installed:
```bash
uv pip install --python .venv-docs --group docs
```
## Viewing the Documentation
After building, open `docs/build/html/index.html` in your, or use Python's built-in HTTP server:
```bash
cd docs/build/html
python -m http.server 8000
# Then visit http://localhost:8000 in your browser
```
...@@ -175,4 +175,4 @@ After adding new documentation: ...@@ -175,4 +175,4 @@ After adding new documentation:
1. **Sphinx (current):** Update `docs/index.rst` or the appropriate `_sections/*.rst` file to include your new docs in the navigation 1. **Sphinx (current):** Update `docs/index.rst` or the appropriate `_sections/*.rst` file to include your new docs in the navigation
2. **Fern (future):** Update `fern/docs.yml` with your new pages 2. **Fern (future):** Update `fern/docs.yml` with your new pages
See [docs/README.md](../README.md) for documentation build instructions. See [docs/README.md](../../README.md) for documentation build instructions.
...@@ -224,6 +224,7 @@ navigation: ...@@ -224,6 +224,7 @@ navigation:
# ==================== Blog ==================== # ==================== Blog ====================
- section: Blog - section: Blog
hidden: true
path: ../blogs/index.mdx path: ../blogs/index.mdx
slug: blog slug: blog
contents: contents:
...@@ -231,6 +232,12 @@ navigation: ...@@ -231,6 +232,12 @@ navigation:
path: ../blogs/flash-indexer/flash-indexer.md path: ../blogs/flash-indexer/flash-indexer.md
slug: flash-indexer slug: flash-indexer
# ==================== Documentation ====================
- section: Documentation
contents:
- page: Dynamo Docs Guide
path: ../README.md
# ==================== Hidden Pages ==================== # ==================== Hidden Pages ====================
# Pages accessible via direct URL but not shown in main navigation. # Pages accessible via direct URL but not shown in main navigation.
# Matches Sphinx hidden_toctree.rst -- pages linked from within content # Matches Sphinx hidden_toctree.rst -- pages linked from within content
...@@ -322,9 +329,6 @@ navigation: ...@@ -322,9 +329,6 @@ navigation:
# -- Mocker -- # -- Mocker --
- page: Mocker - page: Mocker
path: ../pages/mocker/mocker.md path: ../pages/mocker/mocker.md
# -- Docs README --
- page: Building Documentation
path: ../pages/README.md
# -- Templates -- # -- Templates --
- section: Templates - section: Templates
path: ../pages/templates/README.md path: ../pages/templates/README.md
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment