Publishing Documentation
When you publish a library crate to crates.io via cargo publish, docs.rs automatically downloads your crate archive, builds its documentation in an isolated container, and hosts the generated HTML at https://docs.rs/<crate_name>/<version>. For private or application repositories, static target/doc/ output can be deployed directly to GitHub Pages, Cloudflare Pages, or an internal web server.
`cargo publish` ---> crates.io ---> Triggers docs.rs build queue
|
v
Reads `[package.metadata.docs.rs]`
Runs `rustdoc` inside sandboxed container
|
v
Published at `https://docs.rs/<crate>`
Configuring docs.rs Builds in Cargo.toml
By default, docs.rs builds your crate on x86_64-unknown-linux-gnu with default features only. If your crate has optional Cargo features (such as serde, tokio, or tls) that enable additional modules or trait implementations, configure the [package.metadata.docs.rs] table in Cargo.toml so docs.rs enables all features during documentation builds:
[package]
name = "my_network_kit"
version = "0.2.0"
edition = "2024"
description = "Fast framing utilities for network streams"
license = "MIT OR Apache-2.0"
repository = "https://github.com/example/my_network_kit"
documentation = "https://docs.rs/my_network_kit"
readme = "README.md"
[features]
default = []
serde = []
async-io = []
[package.metadata.docs.rs]
# Build documentation on docs.rs with all optional features enabled
all-features = true
# Pass "--cfg docsrs" to rustdoc so unstable `doc_cfg` badges can be rendered
rustdoc-args = ["--cfg", "docsrs"]
# Optionally build docs for additional target triples
targets = ["x86_64-unknown-linux-gnu", "aarch64-apple-darwin", "x86_64-pc-windows-msvc"]
Rendering Feature Badges with doc_cfg / doc_auto_cfg
When [package.metadata.docs.rs] passes --cfg docsrs (which runs on docs.rs's nightly rustdoc builder), enabling #![cfg_attr(docsrs, feature(doc_auto_cfg))] at the top of src/lib.rs automatically renders a blue "Available on crate feature serde only" badge next to every #[cfg(feature = "serde")] item—while still compiling cleanly on stable Rust during normal cargo build and cargo test runs!
// Compiles cleanly on stable Rust; activates `doc_auto_cfg` only when `--cfg docsrs` is passed
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
/// Core frame type always available.
#[derive(Debug)]
pub struct Frame(pub Vec<u8>);
/// Available only when the `"compression"` feature is enabled.
#[cfg(feature = "compression")]
pub fn compress_frame(frame: &Frame) -> Frame {
Frame(frame.0.clone())
}
fn main() {
let f = Frame(vec![1, 2, 3]);
println!("Frame length: {}", f.0.len());
}
Frame length: 3
Avoiding Deduplication Drift with include_str!("../README.md")
To keep your repository's README.md and your crate's top-level src/lib.rs documentation identical—and to have cargo test --doc test every code example inside README.md—embed README.md directly at the top of src/lib.rs:
#![doc = include_str!("../README.md")]
Pre-Publish Local Verification Checklist
Before running cargo publish or pushing a release tag, run these three commands locally to verify your documentation will build cleanly on docs.rs:
# 1. Verify no broken intra-doc links or rustdoc warnings with all features enabled
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features
# 2. Verify all doc-tests compile and pass
cargo test --doc --all-features
# 3. Verify package tarball includes README.md and all required files
cargo package --list