Share rustdoc

Rust's documentation story is excellent right up to the point where the crate is private. docs.rs builds and hosts documentation for everything published to crates.io, beautifully, for free — and has nothing at all to say about your company's internal platform-core crate, which is the one your team actually needs docs for.

So cargo doc output lives in target/doc/ and gets read by whoever ran the command.

Build it

cargo doc --no-deps
# → target/doc/<crate_name>/index.html

--no-deps is close to mandatory. Without it, cargo documents the entire dependency tree — tens of thousands of files for a normal project, which is both unpublishable and not what anyone wanted.

target/doc/
├── my_crate/index.html      # the entry page
├── my_crate/struct.Foo.html # one page per item
├── static.files/            # css, js
└── search-index.js

Drop the folder in

Drag target/doc/ (or a zip of it) into Comma:

  • The crate's index.html becomes the report body — the page carrying the comment layer.
  • Item pages, static.files/ and the search index upload alongside it, with relative references rewritten to the uploaded copies.
  • Scripts run inside a sandboxed iframe (allow-scripts, no allow-same-origin), so search, the theme picker and the expand/collapse controls keep working.

One URL. No bucket, no internal web server, no python -m http.server in a tmux session someone will kill.

From the release job

cargo doc --no-deps

curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html target/doc/my_crate/index.html \
        --arg title "my_crate — $(git describe --tags --always)" \
        '{title: $title, html: $html}')"

The API is JSON-only, so the item pages go up through POST /api/v1/reports/$REPORT_ID/assets as base64 — one call per file, worth scripting once. See the API reference and publishing from CI.

PATCHing one saved id gives the crate a permanent address that tracks the current release, with a revision per publish. That history answers "when did this trait get a new required method?" better than reading the changelog someone forgot to update.

Workspaces

cargo doc --workspace --no-deps documents every member crate into the same target/doc/, cross-linked. Publish the folder and the links between crates resolve, which is the thing that makes workspace docs worth having over per-crate ones.

Watch the file count — see Limits below.

Docs review, on the docs

Rust's type signatures carry a lot, which is exactly why the doc comments tend to be thin: the signature looks self-explanatory, so nobody writes down the part that isn't. What a Result::Err variant actually means, which invariants the constructor assumes, whether the function can block.

Published, that feedback lands on the item. Select the description, leave a thread — "this doesn't say the lock is held across the await" — and it stays anchored to that function across docs builds. See commenting on HTML.

Who can see it

Per report: private, your team, any signed-in user with the link, or public. An internal crate gets a team report. Domain-gating, password gates and expiring links are Enterprise. See sharing & access control.

Limits

  • Entry HTML: 5 MB. Assets: 25 MB per file, 250 MB and 500 files total — the binding constraint. A large workspace's rustdoc exceeds 500 pages easily; publish the crate under review, or the public API surface, rather than everything.
  • Scripts run, sandboxed — no same-origin access.
  • 60 requests/minute per token.

Try it

Comma is free — unlimited reports, unlimited commenters, unlimited revision history.

Publish crate docs →

Related