Building the Docs
This site uses Fern. Page content lives in docs/ as Markdown, and the Fern
configuration lives in docs/fern. Run the commands on this page from docs/fern/ or the repository root
with npm --prefix docs/fern run <script>.
Prerequisites
Before you build or preview the documentation, review the requirements for the task you plan to run:
The Node.js version affects tasks as follows:
- CI validation:
docs/fern/package.jsondeclaresengines.node >= 20, and CI pins Node 20 fornpm run check. Node 18 fails withReferenceError: crypto is not defined. - Development server: Use Node 22.13 or newer for
npm run dev. The server installs the currentpnpmrelease, which declaresnode >= 22.13. - Installation: Use
nvmor another version manager. The development server installspnpmglobally. Installation fails withEACCESwhen npm uses a root-owned global prefix such as/usr/local.
The Fern CLI is not installed globally. Every npm script uses npm exec to fetch and run the exact
version pinned in docs/fern/fern.config.json, so local runs match CI.
Scripts
Use these scripts from docs/fern to generate, validate, preview, or publish the site:
Navigation Is Generated — Do Not Hand-Edit
Fern requires two navigation files with different path conventions, and only one of them is
validated by fern check:
Both are generated from the single source of truth, docs/fern/nav.json, by
docs/fern/scripts/gen-nav.mjs. Manual edits can make a page disappear from one channel while it remains
visible in the other.
To add a page:
gen-nav.mjs also asserts that every page referenced by nav.json exists on disk. If a page is missing, the
script lists it explicitly. This message is clearer than the corresponding fern check or lychee output.
Commit nav.json, versions/nightly.yml, and index.yml together.
Generating the Python API Reference
The Full-Library-Reference section under docs/fern/product-docs/ is generated, gitignored, and
rebuilt on every publish. You do not need it locally for fern check to pass. Generate it only when you
need to view the API pages in the development server.
Generating from a local checkout requires a temporary edit to docs/fern/docs.yml: uncomment the
nemo-voice-agent-local library block.
Re-commenting is mandatory: fern docs dev rejects path-backed libraries during config load with
Library 'nemo-voice-agent-local' uses 'path' input which is not yet supported. The generated pages
under product-docs/ survive the re-comment, so the dev server still serves them.
generate:library:local then runs npm run sanitize:generated. That script rewrites MDX-invalid JavaScript
XML (JSX) attributes that the Python generator emits for Pydantic field types. If you run the generator directly,
also run the sanitizer.
Running the Dev Server
To authenticate Fern and start the local documentation server, run:
If login fails with an organization access error, sign in to the Fern dashboard with an account that has NVIDIA organization access, and then retry.
Authoring Rules CI Enforces
Three gates run on any pull request (PR) that touches docs/ (fern-docs-ci.yml):
- Every raw HTML
imgtag must be self-closing anywhere underdocs/. Prefer plain Markdown images. If you must use HTML, close the tag with a trailing slash. fern checkmust pass.- lychee
--offlineoverdocs/**/*.md. Every relative link target must exist on disk. There is no ignore file—a link to a repository source file that is not a documentation page fails the build. Name source files in inline code instead of linking to them.
Beyond the gates, two authoring conventions matter:
- Write pages as
.md. The.mdxextension is reserved for generated output. - Fern renders
.mdthrough MDX, so a bare{,}, or<outside a fenced code block breaks the build. Put YAML braces, OmegaConf interpolation, type generics, and comparison operators inside fenced code blocks or inline backticks.
A separate pair of workflows (fern-docs-preview-build.yml and fern-docs-preview-comment.yml)
builds a hosted preview and posts the link as a PR comment. The build job runs on the PR branch with
no secrets. The comment job picks up the artifact and builds with the organization token, so previews are
safe on fork pull requests.
Publishing
Merging a documentation change to main publishes the nightly channel live. publish-fern-docs.yml fires
on any push to main that touches docs/**, gated on the repository variable PUBLISH_FERN=true.
There is no manual approval step—review the preview before merging.
Releases are separate. For a published GitHub Release or a manual dispatch with a tag, the same workflow
freezes that tag’s documentation into a versioned channel. It registers the channel in docs.yml, prunes to
the three most recent versions, and opens a pull request to persist the registry change back to main.
Pre-release tags publish but skip version registration.
Related
Use these pages for the repository contribution workflow and test suites:
- Contributing: Branch, lint, and pull request conventions for the repository.
- Testing: How to run the pytest suites.