Skip to content

docs(api): generate typed language references with rendered docstrings - #12110

Merged
dagil-nvidia merged 64 commits into
mainfrom
dagil-nvidia/api-reference-v2
Aug 10, 2026
Merged

docs(api): generate typed language references with rendered docstrings#12110
dagil-nvidia merged 64 commits into
mainfrom
dagil-nvidia/api-reference-v2

Conversation

@dagil-nvidia

@dagil-nvidia dagil-nvidia commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Generate deterministic API references for Python, published Rust crates, and Kubernetes CRDs, rendered entirely from Fern's own MDX components (CardGroup, Accordion, ParamField, Badge) with no bespoke React.
  • Because the pages are plain MDX, Fern indexes the whole surface for search and derives the Markdown / llms.txt twins itself. That replaces the hand-maintained llms-only blocks and gives every page the native "Copy page / View as Markdown / Open in Claude" actions.
  • Colocate all three surfaces under one API Reference section and surface every Python module in the sidebar.
  • Gate generator tests and output freshness in pre-merge and Fern docs CI.

Why Native MDX Rather Than React

The first pass rendered each surface through a React component fed by a generated .data.ts module. Committing to Fern's components instead removed ~1,900 lines of component and data code and fixed three classes of defect that the React version hid:

  • Links were never checked. fern docs broken-links does not inspect hrefs inside JSX, so the landing page's language links pointed at routes that never resolved. As MDX cards they are validated, and now use source paths that survive a slug rename.
  • Content was invisible to search and to agents. Component-rendered schema never reached the Markdown twin, which is why hand-written llms-only twins existed at all.
  • Anchors were hand-rolled. Accordion takes a deep-link id natively; the empty <a id> that preceded each one rendered as a link with no text. Targeting the id now expands the accordion rather than scrolling to a collapsed body.

Fern's Beta Python library generator was evaluated first and does not fit this repo: dynamo is a PEP 420 implicit namespace package, the critical _core surface lives in a .pyi stub, and there is no allowlist for the 11 curated modules. The griffe-based generator stays.

Validation

  • 162 passed in docs/fern/scripts/tests
  • gen_python_api.py --check, gen_rust_api.py --check, gen_kubernetes_api.py --check
  • fern check (0 errors)
  • docs/fern/scripts/check_reference.sh (all checks passed; 0 Reference errors)
  • Local Fern preview: all routes 200; verified the sidebar, cards, accordion bodies (import fence, signature, per-method source links), and a deduped Kubernetes deep link

Dependencies

Update: absorbed #12111, and the API test failure is fixed

#12111 (docstring rendering and per-method anchors) was stacked directly on
this branch, so folding it was a fast-forward with no conflict and no
rewritten history. GitHub marked it merged on its own. This PR is now the
whole API-reference change: generation plus the docstring rendering.

That also cleared one of this PR's two failures. Preview or publish docs was
failing on stale gen_kubernetes_api.py output, which #12111's head commit had
already regenerated.

The remaining Generated API References failure is fixed here. The cause was
not stale output, which is what the check's usual failure mode suggests. A test
hardcoded the release tag:

assert reference.release_tag == "1.3.0"
AssertionError: assert '1.3.1' == '1.3.0'

release_tag derives from CURRENT_TAG in releases.data.ts, which main
bumped to 1.3.1, so a release bump broke a test whose stated subject is the
published and lagging crate matrix. It now asserts against the same derivation
the code under test uses, so the invariant holds across bumps.

Validation: on a linux/python:3.13-slim container with the pinned
griffe==2.1.0, the four API suites pass 190 tests and gen_python_api,
gen_rust_api and gen_kubernetes_api all report --check clean. Running on
Linux mattered: the generated output was never stale, and reproducing on macOS
alone would have kept pointing at the wrong cause.

Summary by CodeRabbit

  • New Features

    • Added a consolidated API Reference hub covering Python, Rust, and Kubernetes APIs.
    • Added expanded generated reference pages with searchable public API details, signatures, schemas, and installation links.
    • Added improved navigation and redirects for Kubernetes API documentation.
  • Documentation

    • Improved callout formatting and API reference page styling.
    • Corrected the documented dynamo-config Rust crate version to 1.2.1.
    • Added automated checks to keep generated API documentation current and consistent.

@dagil-nvidia
dagil-nvidia requested review from a team as code owners July 24, 2026 18:12
@github-actions github-actions Bot added docs documentation Improvements or additions to documentation deployment::k8s Relates to dynamo deployment in kubernetes actions and removed docs labels Jul 24, 2026
@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

Open in Devin Review

Comment thread docs/fern/components/ApiPythonIndex.tsx Outdated
Comment thread deploy/operator/Makefile Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0bd0be40ca

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/fern/scripts/api_rendering.py Outdated
Comment thread .github/filters.yaml Outdated
Comment thread docs/fern/components/KubernetesSchemaDetails.tsx Outdated
Comment thread docs/fern/components/KubernetesSchemaDetails.tsx Outdated
@copy-pr-bot

copy-pr-bot Bot commented Jul 27, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions github-actions Bot added backend::vllm Relates to the vllm backend backend::sglang Relates to the sglang backend backend::trtllm Relates to the trtllm backend planner labels Jul 27, 2026
@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

/ok to test 565aea7

…tions

The three language surfaces were not peers in the sidebar. Kubernetes API
sat at the top level with an icon while Python and Rust were nested one
level down inside a generic 'API Reference' section, so the tab a reader
opens to look up a symbol led with a wrapper rather than with the
languages.

Python API and Rust API now sit alongside Kubernetes API, each with its
brand icon. The 'API Reference' landing page stays as a top-level page at
the same slug.

Slugs are pinned to 'api/python' and 'api/rust' rather than following the
new nav depth. Fern derives URLs from nav structure, so a plain move would
have rewritten every /reference/api/... URL -- including the twenty
anchored redirects in docs.yml that carry the retired NIXL Connect class
pages into the generated module page. Nested slugs keep every published
URL byte-identical while the sidebar changes.

Python API keeps collapsed: false. That was a deliberate call recorded in
the surrounding comment -- Fern collapses by default, which hid the whole
published module surface behind a click -- and promoting the section does
not change the reasoning.

Validation: fern check reports 0 errors; all three generators --check
clean (the nav moved, the generated files did not); generator tests pass.

Signed-off-by: Dan Gil <dagil@nvidia.com>
@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

/ok to test b74e331

Promoting Python and Rust made them peers of Kubernetes but left the group
incoherent in two ways, both visible in the preview.

In the sidebar, Kubernetes API rendered eight entries below Rust -- past
Compatibility, Examples, Releases and Glossary -- so the three language
surfaces never read as a group. It now sits directly after Rust.

In the URL space, Python and Rust were pinned under 'api/' while Kubernetes
sat beside that family at /reference/kubernetes-api. All four now share one
prefix:

    /reference/api             landing
    /reference/api/python
    /reference/api/rust
    /reference/api/kubernetes

This is a slug change only. The pages stay at
pages/reference/kubernetes-api/, so the generator, .github/filters.yaml, and
all 29 in-tree links to those pages are untouched -- every one of them is a
relative file link, and none is an absolute route. The directory name no
longer matches its route, which is the price of not churning a generated
tree for a naming change.

The /reference/kubernetes-api/* routes were published, so all six redirect
into the new family, and the six existing redirects that pointed at them
were re-pointed rather than left to chain.

Tests cover both invariants: all four slugs asserted together against a
later 'tidy' that would silently move routes, and contiguity asserted so the
group cannot drift apart again.

Validation: 204 tests pass; fern check 0 errors; all three --check clean.
Signed-off-by: Dan Gil <dagil@nvidia.com>
@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

/ok to test ac6abc1

The landing page is the first thing the Reference tab shows, and its three
cards were the only place Python, Rust and Kubernetes appeared without the
icons their sidebar entries carry -- so the page presented a different
visual vocabulary than the nav sitting next to it.

Each card now takes the same fa-brands icon as its sidebar entry, in the
tree's usual title / icon / href prop order. The bodies were trimmed to
within a few characters of each other so the three cells render as even
thirds rather than one tall card and two short ones; cols={3} already
handled the widths.

Native Card props only. This surface renders through stock Fern MDX and
owns no React components, which a regression test enforces.

Adjusted test_api_landing_points_kubernetes_at_colocated_route: its regex
matched 'title' immediately followed by 'href', so inserting the icon prop
between them would have failed a test that has nothing to do with icons.
Added a companion test pinning each card's icon to its sidebar entry.

Validation: 205 tests pass; fern check 0 errors; all three --check clean.
Signed-off-by: Dan Gil <dagil@nvidia.com>
@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

/ok to test dddc0b4

…ions

The Reference tab holds three kinds of entry: flat informational pages
(Compatibility, Examples, Releases, Glossary), the API surfaces, and the
configuration sections (Components, Backends, Observability, NIXL Connect).
Leading the tab with the API block split the two groups of expandable
sections across the whole sidebar with the flat pages wedged between them.

The API block now sits directly above Components, so every expandable
reference section is one run at the bottom and the flat pages read as the
tab's preamble.

Nothing else changes: the four API entries stay contiguous, keep their
icons, and keep their pinned api/ slugs, so no route moves. The contiguity
test asserts relative position rather than an index, so it covers the block
wherever it sits.

Validation: 205 tests pass; fern check 0 errors; all three --check clean.
Signed-off-by: Dan Gil <dagil@nvidia.com>
@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

/ok to test 319ab68

The tab had grown by accretion: Examples sat second, Glossary sixth, and
the two runs of expandable sections were split by the flat pages between
them. Nothing about the order told a reader where to look.

Four groups now, in the order a question tends to arrive:

  versions      Compatibility, Releases, Release Artifacts,
                Nightly Releases, Model Early Access Builds
  API surfaces  API Reference, Python API, Rust API, Kubernetes API
  config        Components, Backends, Observability, NIXL Connect
  supporting    Examples, Glossary

Compatibility leads because "will this run with what I have" precedes
every other question, and the release pages descend by stability from
shipped to nightly to early access. Examples and Glossary move to the
bottom: both are browsed, not looked up.

Renamed 'Nightly Release Info' to 'Nightly Releases'. Its slug is pinned,
so the URL does not move, and the page frontmatter title follows the nav
label.

Reordering nav by script is how entries go missing, so the change was
diffed structurally rather than read: 16 entries before and after, all 61
page paths an identical set, and the only delta the intended rename.
Comments were re-attached to the entries they document.

Corrected the stale rationale on Python API's 'collapsed: false'. It cited
the block being the first thing on the tab, which stopped being true when
the block moved down.

Validation: 205 tests pass; fern check 0 errors; all three --check clean.
Signed-off-by: Dan Gil <dagil@nvidia.com>
@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

/ok to test 30dac1a

Python API shipped expanded while Kubernetes API collapsed. That read as an
oversight once the two became peers: eleven 'dynamo.*' rows stood open beside
a Kubernetes section folded to one line. Both collapse now, so the four API
entries occupy four rows and a reader opens the surface they came for.

'How It Stays Current' shrinks from a 26-line section to one admonition, and
is corrected in the process. It was wrong on the point this PR exists to
make: it said --check runs 'against every commit', when the pre-merge job
passes --since <base> on a pull request to scope the gate to the branch's own
changes and only runs strict on main. It also documented gen_python_api.py
alone while the page's own three cards cover Python, Rust and Kubernetes.

What was cut was restating the generator's file layout and local invocation
-- reference material for someone editing the generator, not for a reader who
came to look up a symbol, and it now lives in docs/fern/AGENTS.md next to the
other machinery gates.

test_python_api_section_is_expanded_by_default asserted the opposite of the
new setting, so it became test_api_sections_collapse_consistently and now
pins both sections rather than one.

Validation: 205 tests pass; fern check 0 errors; all three --check clean.
Signed-off-by: Dan Gil <dagil@nvidia.com>
@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

/ok to test 6597a9b

Both places I described the pipeline said gen_kubernetes_api.py reads the
operator Go types. It does not. It parses
pages/reference/kubernetes-api/additional-resources/api-reference-k8s.md, a
committed Markdown file that 'make generate-api-docs' in deploy/operator/
produces by running crd-ref-docs over the CRD types.

The distinction is the whole point for anyone acting on the instruction:
editing a Go type and rerunning gen_kubernetes_api.py is a no-op, because the
renderer re-reads an intermediate nothing has refreshed. Python and Rust are
one hop and behave the way the old text described; Kubernetes is two, and the
first hop lives outside docs/ in a different Makefile.

Corrected the landing-page admonition and the docs/fern/AGENTS.md gate, the
latter with both commands in order so the sequence is not left implicit.

Validation: make -C deploy/operator -n generate-api-docs resolves and its
recipe writes exactly that path; 205 tests pass; fern check 0 errors; all
three --check clean.

Signed-off-by: Dan Gil <dagil@nvidia.com>
@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

/ok to test 6eb381b

#12388 merged and moved main 8 commits, conflicting on
.github/workflows/pre-merge.yml. Both sides add an output to the changed-files
job: this branch adds api_docs, main adds fern_components. Different outputs
for different filters, so the resolution is the union -- dropping either would
leave a job keyed on an output that no longer exists.

The merge also brought Python source changes that alter docstrings the
reference renders, so gen_python_api.py --check went stale on content this
branch never touched. Regenerated; common.mdx was the only page affected.

That is the case this PR's own docs describe: a branch's generated output goes
stale on unrelated main churn, and the freshness gate attributes it to the
branch, so the regeneration has to happen at merge time rather than earlier in
review.

Validation: both changed-files outputs present and each defined in
filters.yaml; workflow YAML parses with 6 outputs; all three generators
--check clean; 205 tests pass; fern check 0 errors.

Signed-off-by: Dan Gil <dagil@nvidia.com>
@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

/ok to test baafcd1

Two fixes, one of them undoing my own damage.

The card blurbs were trimmed in an earlier commit to make the three cells
render as even thirds. That was unnecessary and it cost accuracy: CSS grid
stretches row heights on its own, measured at 260x242 for all three
regardless of text length, so the trimming bought nothing visually. What it
did buy was two wrong descriptions -- the Python card dropped 'mocker' even
though dynamo.mocker is one of the eleven curated modules the page indexes,
and the Kubernetes card said 'resource fields' where 'custom-resource fields'
is the precise term for CRDs.

Restored both and stopped optimizing for character count. The Python card now
states the module count, checked against api_discovery.MODULES rather than
asserted.

Examples moves above the API Reference block in the Reference tab. Glossary
stays at the bottom.

Validation: MODULES is 11, matching the card; 142 tests pass; all three
generators --check clean; fern check 0 errors.

Signed-off-by: Dan Gil <dagil@nvidia.com>
@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

/ok to test 20c39de

Renaming the page to 'Nightly Releases' left slug: nightly-release-info
behind. The slug was pinned deliberately at the time so the published URL
would not move, but the result reads as a leftover: a page called Nightly
Releases serving from .../nightly-release-info.

Now /reference/nightly-releases. The retired route redirects to it, and the
two existing redirects that pointed at the old destination were re-pointed
rather than left to chain through it.

Audited every slug in the Reference tab while here. The rest are deliberate
and stay:

  * 'Dynamo v1.3.0' -> v1-3-0 drops a redundant prefix.
  * Python module pages use _core, health_check, logits_processing and
    nixl_connect rather than hyphenated forms. They mirror the import path
    exactly, which is the point in an API reference -- /api/python/health_check
    maps to dynamo.health_check with no translation -- and twenty anchored
    redirects for the retired NIXL Connect class pages target nixl_connect.
  * api, api/python, api/rust and api/kubernetes are the pinned family that
    keeps the four surfaces on one route prefix.

Validation: no redirect still lands on the retired route; the retired route
redirects; 470 redirects total; fern check 0 errors; 38 nav regressions pass.

Signed-off-by: Dan Gil <dagil@nvidia.com>
@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

/ok to test 85664d1

The page is labelled Nightly Releases and now serves from
/reference/nightly-releases, so nightly-release-info.md was the last piece
still carrying the old name. Renamed with git mv and the single index.yml
reference updated; nothing else in the tree referenced the old path.

The slug is unchanged by this, so no URL moves and the redirects added in the
previous commit still apply.

Validation: no reference to the old filename remains anywhere in the tree;
fern check 0 errors.

Signed-off-by: Dan Gil <dagil@nvidia.com>
@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

/ok to test 5d984e4

Clean auto-merge, no conflicts, one commit behind.

All three generators re-checked after the merge rather than assumed, since a
branch's generated output goes stale whenever main touches a symbol it
documents: this time nothing did, so no regeneration was needed.

Validation: gen_python_api, gen_rust_api and gen_kubernetes_api --check all
clean; 205 tests pass.

Signed-off-by: Dan Gil <dagil@nvidia.com>
@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

/ok to test 4d39334

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

actions deployment::k8s Relates to dynamo deployment in kubernetes docs documentation Improvements or additions to documentation planner size/XXL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants