Home
Content

Rustdoc Integration

Document Rust crates from rustdoc JSON, with doctests extracted as a first-class view.

Sourcey generates Rust API reference documentation from rustdoc's JSON output. A rustdoc() source tab renders crates, modules, items, and doctests with the same navigation, search, and theming as every other tab type. Anchor IDs follow rustdoc's own conventions, so docs.rs-style deep links into your pages keep resolving.

Note

Requires Sourcey 3.6.1 or later.

How it works

rustdoc emits machine-readable JSON on the nightly toolchain. Sourcey ships a bundled Rust helper crate, sourcey-rustdoc, that runs rustdoc and converts its JSON into a stable v1 RustdocSpec snapshot. The adapter reads that snapshot, either fresh from the helper (live mode) or from a committed file (snapshot mode), and renders static pages.

Prerequisites

Live mode needs a nightly Rust toolchain:

rustup toolchain install nightly

Snapshot mode needs no Rust toolchain at all. Commit a generated rustdoc.json and the docs build runs anywhere Node runs.

Configuration

Add a rustdoc() source tab to your config. The manifest path is relative to sourcey.config.ts.

import { defineConfig, rustdoc } from "sourcey";

export default defineConfig({
  navigation: {
    tabs: [
      {
        tab: "Rust API",
        slug: "rust-api",
        source: rustdoc({
          manifest: "../Cargo.toml",
          mode: "auto",
        }),
      },
    ],
  },
});

For the common case, pass the manifest path directly: rustdoc("../Cargo.toml").

Options

OptionDefaultDescription
manifest.Path to a Cargo.toml, or a directory containing one
cratesthe manifest packageCrate names to document
snapshotnonePath to a committed rustdoc.json snapshot
mode"auto""auto", "live", or "snapshot"
features{ default: true }Feature selection: default, list, all
includePrivatefalseInclude pub(crate) and private items
includeHiddenfalseInclude items marked #[doc(hidden)]
targethost targetTarget triple to build docs for
toolchain"nightly"rustup toolchain name (use a dated pin if you need one)
sourceBasePath""Repository-relative base path for source links
doctestsIndextrueRender a dedicated doctests index page

Modes

  • auto (default): probe rustup toolchain list for the configured toolchain. If present, run the bundled helper. Otherwise read the snapshot, with an info diagnostic (RUSTDOC_AUTO_FELL_BACK_TO_SNAPSHOT).
  • live: always run the bundled helper. Fails if the toolchain is missing.
  • snapshot: always read the committed snapshot. Fails if no snapshot path is configured.

When neither mode is viable, the build fails with RUSTDOC_NO_VIABLE_MODE and prints the exact rustup toolchain install and snapshot-config commands that fix it.

The sourcey-rustdoc binary

The bundled helper ships inside the npm package at node_modules/sourcey/dist/core/sourcey-rustdoc and compiles through Cargo on the first live-mode run. Cold compile takes 30 to 60 seconds; later invocations are near-instant. The same crate is published standalone as sourcey-rustdoc on crates.io for tools that drive snapshot generation from Rust.

sourcey-rustdoc --manifest <path> [options] [--output <file>|-]

Key flags: --crate, --features, --all-features, --no-default-features, --include-private, --include-hidden, --target, --toolchain, --output (- writes to stdout), and --strict to exit non-zero on any error-level diagnostic.

Snapshot mode for CI on stable

CI hosts rarely carry a nightly toolchain. Generate a snapshot locally or in a dedicated job, commit it, and the docs build reads it on stable Rust, or on hosts with no Rust at all. A minimal generation script runs the bundled helper directly:

// scripts/snapshot-rustdoc.mjs
import { spawnSync } from "node:child_process";

const result = spawnSync(
  "cargo",
  [
    "run", "--release", "--quiet",
    "--manifest-path", "./node_modules/sourcey/dist/core/sourcey-rustdoc/Cargo.toml",
    "--",
    "--manifest", "./Cargo.toml",
    "--toolchain", "nightly",
    "--output", "./snapshots/rustdoc.json",
  ],
  { stdio: "inherit" },
);
process.exit(result.status ?? 1);

Then point the tab at the snapshot:

source: rustdoc({
  manifest: "../Cargo.toml",
  snapshot: "./snapshots/rustdoc.json",
  mode: "snapshot",
}),

When you upgrade Sourcey, regenerate the snapshot with the same pinned nightly. If the rustdoc JSON format moves between versions, the build reports RUSTDOC_FORMAT_VERSION_MISMATCH with a remedy.

What gets rendered

  • A workspace index with one card per crate, and a crate overview with one card per module
  • One page per module, with constants, statics, functions, types, traits, macros, and re-exports rendered inline as sections
  • Signatures with clickable cross-references; intra-doc links of the form [`Foo`] resolve to internal pages, doc.rust-lang.org for std/core/alloc, or docs.rs for external crates
  • Trait implementations collapsed behind a single disclosure, with auto and marker traits as a quiet list
  • Every item flows into the search index, llms.txt, llms-full.txt, and sitemap.xml

Doctests

Every code fence inside a /// or //! doc comment is extracted and rendered with:

  • Hidden #-prefixed lines stripped from the display copy, with a toggle to show them
  • Badges for ignore, no_run, should_panic, compile_fail, and editionYYYY fence attributes, each with a tooltip
  • A Run button that opens the example in the Rust Playground with the right edition
  • A copy button

With doctestsIndex enabled (the default), a dedicated Doctests page aggregates every runnable example across the workspace, grouped by parent item and linked back to its source.