How to Use Markdown in Rust Documentation

Write Markdown files in the src directory and run mdbook build to generate HTML documentation.

When a README isn't enough

You have written a library. The README starts as a simple installation guide and a usage example. Then you add a troubleshooting section. Then a comparison with other crates. Then a detailed explanation of the architecture. The file grows to four hundred lines. You try to add a table of contents, but it is just a list of anchors that break every time you rename a header. You need a documentation system that handles structure, navigation, and updates automatically. You need a way to split the content into pages without losing the flow.

Rust projects solve this with mdbook. It is a command-line tool that takes a folder of Markdown files and a summary file, then compiles them into a static website. You write plain Markdown. mdbook handles the HTML, CSS, search, and navigation. The result is a polished documentation site that looks professional and scales from a single tutorial to a multi-hundred-page guide.

The two lanes of Rust documentation

Rust documentation splits into two distinct lanes. Understanding the difference prevents a common mistake where beginners dump tutorials into code comments.

The first lane is cargo doc. This tool extracts documentation from your source code. It reads the /// doc comments above functions, structs, and modules. It generates an API reference. It tells you what a function does, what arguments it takes, and what it returns. It lives in the code. It is tightly coupled to the implementation.

The second lane is mdbook. This tool lives outside the code. It builds guides, tutorials, and architectural overviews. It treats documentation as a separate artifact that happens to live in the same repository. It is not generated from code comments. You write the content in Markdown files. It is designed for human readers who need context, examples, and step-by-step instructions.

Convention aside: The Rust community treats mdbook as the standard for project documentation. If you look at the docs for serde, tokio, or axum, you will see a "Book" link. That is mdbook. Following this convention makes your project feel familiar to other Rust developers. They know where to find the guide and where to find the API reference.

Setting up mdbook

mdbook is a tool, not a crate. You do not add it to Cargo.toml. You install it on your machine, just like cargo itself.

# Install the tool. This downloads the binary to your local toolchain.
# You do not use mdbook in Rust code. It is a build tool.
cargo install mdbook

Once installed, you can initialize a new book in any directory.

# Create the skeleton for a documentation book.
# This generates src/, SUMMARY.md, and book.toml.
mdbook init my-docs

The command creates a standard structure.

my-docs/
├── book.toml
└── src/
    ├── SUMMARY.md
    └── intro.md

The src/ directory holds your Markdown files. The SUMMARY.md file defines the structure. The book.toml file holds configuration. The book/ directory will appear after you build, containing the generated HTML. Add book/ to your .gitignore. Generated files belong in the build cache, not version control.

The anatomy of a book

The heart of mdbook is SUMMARY.md. This file is the source of truth for your documentation. If a file is not listed in the summary, it does not exist in the book. The tool enforces this strictly.

# Summary

[Introduction](intro.md)

# Getting Started

- [Installation](installation.md)
- [Configuration](configuration.md)

# Advanced Topics

- [Performance](performance.md)
- [Security](security.md)

The syntax is simple but precise. A # Header line creates a section. A list item - [Title](file.md) creates a page. Indentation creates nesting. A part header is just a # Header line. A page is a list item. The order in SUMMARY.md determines the order in the navigation sidebar.

Convention aside: Name your files to match the titles in the summary. installation.md for "Installation". This keeps the file system and the navigation in sync. It makes it easy to find the source file for a specific page.

Links inside your Markdown files should be relative. Use [Link](other.md). Do not use absolute paths. mdbook rewrites relative links to point to the correct HTML files during the build. If you use absolute links, they break when you move the book or change the directory structure. Trust the tool to handle the paths. Write relative links.

Building and serving

Run mdbook build to compile the documentation.

# Process all Markdown files and generate the static site.
# Output goes to the book/ directory by default.
mdbook build

The command reads book.toml for configuration. It parses SUMMARY.md. It finds every Markdown file listed in the summary. It renders HTML. It copies assets. It writes the result to book/. If a file is missing, the build fails. If a link is broken, the build warns. The process is strict. This prevents dead links and missing pages from reaching your readers.

During development, use mdbook serve instead.

# Start a local server with live reload.
# The browser refreshes automatically when you save a file.
mdbook serve

The server starts on localhost:3000. It watches for changes in src/. When you save a Markdown file, the server rebuilds the book and pushes the update to the browser. You do not need to refresh manually. This workflow makes writing documentation fast and iterative. You can see the result of every edit immediately.

Realistic configuration

book.toml controls the output. The default configuration works for most projects. You can customize the theme, enable search, and add repository links.

[book]
authors = ["Your Name"]
language = "en"
multilingual = false
src = "src"

[output.html]
mathjax-support = false
git-repository-url = "https://github.com/user/repo"
edit-url-template = "https://github.com/user/repo/edit/main/docs/{path}"

The [book] section sets metadata. The authors field appears in the HTML metadata. The language field sets the HTML lang attribute. The src field points to the directory containing your Markdown files.

The [output.html] section controls the HTML renderer. Setting git-repository-url adds a "GitHub" link in the top right corner. Setting edit-url-template adds an "Edit this page" link on every page. The {path} placeholder is replaced with the path to the Markdown file. This link jumps directly to the file in GitHub. It encourages readers to contribute fixes and improvements.

Convention aside: Always configure edit-url-template for public projects. It lowers the barrier to contribution. Readers can fix typos or update examples with a single click. It turns passive readers into active maintainers.

mdbook also supports preprocessors. These are plugins that run before the HTML generation. You can add link checking, Mermaid diagrams, or custom transformations. The community maintains preprocessors for common needs. You enable them in book.toml.

[preprocessor.linkcheck]
command = "mdbook-linkcheck"

This example adds a link checker. It scans your Markdown files and verifies that all links are valid. It catches broken links before you publish. It is a small addition that saves hours of debugging later.

Pitfalls and gotchas

mdbook is straightforward, but a few patterns cause friction.

Relative links are mandatory. If you write [Link](/absolute/path.md), the link breaks. mdbook does not rewrite absolute links. It assumes they point to external resources. Write [Link](path.md) and let the tool handle the rest.

Summary syntax errors halt the build. If you mess up the indentation in SUMMARY.md, mdbook fails with a parse error. The error message points to the line number. Fix the indentation. The list structure must be valid Markdown.

Do not mix cargo doc and mdbook content. Beginners sometimes put tutorials in /// comments and expect mdbook to pick them up. It does not. mdbook reads Markdown files. cargo doc reads code comments. They are separate tools. Keep guides in mdbook. Keep API docs in code.

The output directory is book/ by default. If you commit this directory, you will get merge conflicts every time you build. Add book/ to .gitignore. The generated HTML is reproducible. Anyone can rebuild it from the source. Version control is for source, not artifacts.

Decision matrix

Choose the right tool for the job. Rust has multiple documentation options. Use the right one based on your needs.

Use mdbook when you need a multi-page guide, tutorial, or architecture document. Use mdbook when you want a polished static site with search, navigation, and live reload. Use mdbook when your documentation is too large for a single README.

Use cargo doc when you are documenting the public API of a crate. Use cargo doc when you need to generate reference docs from code comments. Use cargo doc when you want the documentation to stay in sync with the code automatically.

Use a README.md when you have a single page of information for a repository. Use a README.md when the project is small and does not need a full documentation site. Use a README.md when you want the documentation to be visible on GitHub without clicking through.

Use a wiki when the documentation is community-maintained and changes constantly outside the code repository. Use a wiki when you need discussion threads attached to documentation pages. Use a wiki when the docs are not part of the release process.

Keep tutorials out of doc comments. Doc comments are for the compiler and the API reference. mdbook is for the human reader. Treat SUMMARY.md as the table of contents and the build manifest. If it is not in the summary, it is not in the book. Run mdbook serve during development. It reloads on save. Stop building manually.

Where to go next