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.htmlbecomes 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, noallow-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.