rust-lang/mdBook
Create book from markdown files. Like Gitbook but implemented in Rust
Healthy across the board
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 3d ago
- ✓14 active contributors
- ✓MPL-2.0 licensed
Show all 6 evidence items →Show less
- ✓CI configured
- ✓Tests present
- ⚠Concentrated ownership — top contributor handles 70% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/rust-lang/mdbook)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/rust-lang/mdbook on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: rust-lang/mdBook
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/rust-lang/mdBook shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit 3d ago
- 14 active contributors
- MPL-2.0 licensed
- CI configured
- Tests present
- ⚠ Concentrated ownership — top contributor handles 70% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live rust-lang/mdBook
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/rust-lang/mdBook.
What it runs against: a local clone of rust-lang/mdBook — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in rust-lang/mdBook | Confirms the artifact applies here, not a fork |
| 2 | License is still MPL-2.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 33 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of rust-lang/mdBook. If you don't
# have one yet, run these first:
#
# git clone https://github.com/rust-lang/mdBook.git
# cd mdBook
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of rust-lang/mdBook and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "rust-lang/mdBook(\\.git)?\\b" \\
&& ok "origin remote is rust-lang/mdBook" \\
|| miss "origin remote is not rust-lang/mdBook (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MPL-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MPL-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is MPL-2.0" \\
|| miss "license drift — was MPL-2.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "crates/mdbook-core/src/lib.rs" \\
&& ok "crates/mdbook-core/src/lib.rs" \\
|| miss "missing critical file: crates/mdbook-core/src/lib.rs"
test -f "crates/mdbook-driver/src/lib.rs" \\
&& ok "crates/mdbook-driver/src/lib.rs" \\
|| miss "missing critical file: crates/mdbook-driver/src/lib.rs"
test -f "crates/mdbook-core/src/config.rs" \\
&& ok "crates/mdbook-core/src/config.rs" \\
|| miss "missing critical file: crates/mdbook-core/src/config.rs"
test -f "crates/mdbook-html/src/html" \\
&& ok "crates/mdbook-html/src/html" \\
|| miss "missing critical file: crates/mdbook-html/src/html"
test -f "crates/mdbook-driver/src/builtin_preprocessors/mod.rs" \\
&& ok "crates/mdbook-driver/src/builtin_preprocessors/mod.rs" \\
|| miss "missing critical file: crates/mdbook-driver/src/builtin_preprocessors/mod.rs"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 33 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~3d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/rust-lang/mdBook"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
mdBook is a Rust-based static site generator that converts Markdown files into a polished online book with a searchable sidebar, syntax highlighting, and theme switching—similar to Gitbook but written entirely in Rust and optimized for technical documentation. It compiles book projects defined in book.toml with custom frontmatter into self-contained HTML output, and ships with built-in preprocessors (for links, code inclusion) and a live-reload dev server. Monorepo with four core crates under crates/: mdbook-core (book model and config parsing), mdbook-driver (preprocessor/renderer orchestration), mdbook-html (HTML rendering backend), and mdbook-markdown (passthrough renderer). Top-level binary (.) ties them together via Cargo workspace. Handlebars templates in crates/mdbook-html drive HTML generation; builtin_preprocessors in mdbook-driver handle link resolution and code inclusion via regex.
👥Who it's for
Technical writers and software teams maintaining project documentation, language guides (like the Rust Book itself), and API docs who want a lightweight, self-hosted alternative to Gitbook without JavaScript dependencies. Contributors are Rust developers interested in static site generation, templating, and CLI tool architecture.
🌱Maturity & risk
Production-ready and actively maintained: it powers the official Rust documentation ecosystem and has CI/CD workflows for every commit, a monorepo structure with semantic versioning (0.5.2), and comprehensive test suites in crates/mdbook-core/src/book/tests.rs. The project has strong governance (Mozilla Public License v2.0) and was last updated within the current dependency refresh cycle (see .github/workflows/update-dependencies.yml), indicating active maintenance.
Low risk for stable uses; however, this is a v0.x crate (version 0.5.2) with explicit backwards-compatibility constraints noted in Cargo.toml (pulldown-cmark pinned as part of public API). The workspace.lints enforce exhaustive_enums and exhaustive_structs, suggesting API surface is intentionally strict. Single-repo for the ecosystem, but distributed across crates/ with clear boundaries, reducing single-point-of-failure risk.
Active areas of work
Active dependency maintenance via renovate.json5 automation and update-dependencies.sh workflow. Recent structure includes mdbook-compare crate (likely new comparison tool), builtin preprocessor refactoring (links/ subdirectory organization), and CI pipeline maturation (deploy.yml for releasing). No explicit milestone data in file list, but update frequency and test infrastructure suggest incremental feature development.
🚀Get running
git clone https://github.com/rust-lang/mdBook.git
cd mdBook
cargo build
cargo run -- serve # Builds and serves example book locally on port 3000
Requires Rust 1.88.0+ (see workspace.package rust-version and .github/workflows/main.yml).
Daily commands:
cargo run -- serve
Starts dev server with live-reload watching book source. For release build: cargo build --release. See .github/workflows/main.yml for full CI test matrix (runs on Rust stable + MSRV 1.88.0).
🗺️Map of the codebase
crates/mdbook-core/src/lib.rs— Core library entry point; defines the fundamental Book structure and loading logic that all other components depend on.crates/mdbook-driver/src/lib.rs— Driver orchestration layer; coordinates preprocessors, renderers, and the entire book build pipeline.crates/mdbook-core/src/config.rs— Configuration parsing and schema; all book behavior is controlled through this config layer.crates/mdbook-html/src/html— HTML rendering engine; converts preprocessed markdown to the final HTML output with templating.crates/mdbook-driver/src/builtin_preprocessors/mod.rs— Preprocessor pipeline definition; shows how markdown is transformed before rendering.Cargo.toml— Workspace manifest defining all crates, dependencies, and MSRV; required reading for build and versioning decisions.CONTRIBUTING.md— Contribution guidelines and development workflow; establishes expectations for code quality and testing.
🛠️How to make changes
Add a Custom Preprocessor
- Create a new module in
crates/mdbook-driver/src/builtin_preprocessors/implementing thePreprocessortrait (crates/mdbook-driver/src/builtin_preprocessors/mod.rs) - Register the preprocessor in the builtin registry by adding it to the module exports (
crates/mdbook-driver/src/builtin_preprocessors/mod.rs) - Implement
fn name()andfn run()methods to define transformation logic on chapters (crates/mdbook-driver/src/builtin_preprocessors/links.rs) - Update config schema in
crates/mdbook-core/src/config.rsto add any configuration options (crates/mdbook-core/src/config.rs) - Add integration tests in the preprocessor module's test section (
crates/mdbook-driver/src/builtin_preprocessors/links/take_lines.rs)
Add a Custom Renderer
- Create a new file in
crates/mdbook-driver/src/builtin_renderers/implementing theRenderertrait (crates/mdbook-driver/src/builtin_renderers/mod.rs) - Implement
fn name()andfn render()methods; receive the processedBookand output target format (crates/mdbook-driver/src/builtin_renderers/markdown_renderer.rs) - Register the renderer in builtin registry (
crates/mdbook-driver/src/builtin_renderers/mod.rs) - Add configuration parsing in
crates/mdbook-core/src/config.rsunder[output.<renderer-name>](crates/mdbook-core/src/config.rs) - Leverage Book structure from
crates/mdbook-core/src/book.rsto traverse chapters and sections (crates/mdbook-core/src/book.rs)
Modify HTML Rendering or Theming
- Edit Handlebars templates in
crates/mdbook-html/front-end/templates/to change layout or structure (crates/mdbook-html/front-end/templates/index.hbs) - Update CSS in
crates/mdbook-html/front-end/css/to change visual styling (general.css for layout, variables.css for colors) (crates/mdbook-html/front-end/css/general.css) - Modify JavaScript in
crates/mdbook-html/front-end/js/book.jsfor client-side behavior changes (crates/mdbook-html/front-end/js/book.js) - Update the HTML renderer backend in
crates/mdbook-html/src/htmlto adjust how chapters are converted to HTML (crates/mdbook-html/src/html)
Add a New Configuration Option
- Define the new configuration struct/field in
crates/mdbook-core/src/config.rswith#[serde(...)]annotations (crates/mdbook-core/src/config.rs) - Make the config accessible from the driver via
crates/mdbook-driver/src/mdbook.rsor relevant renderer/preprocessor (crates/mdbook-driver/src/mdbook.rs) - Document the new option in the User Guide (in
guide/directory, not shown in file list) (crates/mdbook-core/src/config.rs) - Add tests in
crates/mdbook-core/src/book/tests.rsto verify parsing and defaults (crates/mdbook-core/src/book/tests.rs)
🔧Why these technologies
- Rust — Fast compilation and execution; memory-safe; single binary with no runtime dependencies; ideal for static site generation tooling.
- Handlebars templating — Logic-less templates prevent over-complexity in HTML generation; widely familiar syntax; supports partials for modular front-end code.
- TOML configuration — Human-readable; hierarchical; standard in Rust ecosystem; easily extensible for new book options.
- Preprocessor/Renderer plugins — Plugin architecture allows extensibility without core changes; external commands enable language-agnostic custom processors.
- ElasticLunr search — Lightweight full-text search
🪤Traps & gotchas
Pulldown-cmark pinning: Cargo.toml explicitly pins pulldown-cmark version as 'part of the public api'—upgrading requires semver bump and user communication. Edition 2024: workspace enforces Rust 2024 edition; local Rust must be ≥1.88.0 (checked in workflows). Template resolution: Handlebars templates are compiled into binary; theme changes require recompilation. Link preprocessor state: links/take_lines.rs uses regex-based line extraction—brittle if code formatting changes unexpectedly. Workspace lints enforcement: clippy::exhaustive_enums and exhaustive_structs are warnings, not allows; PRs without exhaustive pattern matching will fail CI.
🏗️Architecture
💡Concepts to learn
- Static site generation with live-reload — mdBook's dev server uses notify-debouncer-mini to watch source files and trigger rebuilds—understanding event-based file watching is key to extending the local development experience
- Preprocessor pipeline architecture — mdBook's extensibility relies on chaining preprocessors (see builtin_preprocessors/mod.rs) that each transform the book tree before rendering; understanding this pipeline is essential for custom extensions
- Template rendering with Handlebars — HTML output is generated via compiled Handlebars templates, not string concatenation; learning the template syntax and partial composition is needed to customize book appearance
- Markdown AST transformation via pulldown-cmark — The pulldown-cmark dependency (pinned as public API) parses Markdown into an event stream; preprocessors and renderers manipulate this AST, not raw text
- Workspace-based Rust project organization — mdBook is a multi-crate workspace (core, driver, html, markdown, etc.) with shared dependencies; understanding Cargo workspace resolution is needed to modify the dependency graph
- Semantic versioning constraints in public APIs — Cargo.toml explicitly manages version constraints (e.g., pulldown-cmark 0.13.3 is part of public API); understanding semver and public API stability is critical for contributions
- DOM manipulation with ego-tree — The ego-tree crate provides tree operations for HTML/XML manipulation in preprocessors; understanding tree traversal and mutation is needed for link resolution and code injection
🔗Related repos
rust-lang/mdBook— This is the primary mdBook repository; all related crates are vendored heregetzola/zola— Alternative Rust static site generator with similar goals (Markdown → static HTML) but optimized for blogs and general sites rather than long-form booksGitbookIO/gitbook— The original JavaScript-based Gitbook that inspired mdBook's design; mdBook is the Rust reimplementation with offline-first and CLI-first UXrust-lang/rust— Major consumer of mdBook; the official Rust Book and language documentation are built with mdBook and serve as canonical examplesrust-lang/rfcs— Companion repo where mdBook's own documentation and contribution guides are sometimes cross-referenced or discussed
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive integration tests for the mdbook-driver preprocessor pipeline
The crates/mdbook-driver/src/builtin_preprocessors/ directory contains three preprocessors (cmd.rs, index.rs, links.rs) but there are no visible integration tests verifying their interaction with the book loading pipeline. The mdbook-driver/src/mdbook/tests.rs file exists but likely doesn't cover preprocessor edge cases like malformed links, missing files, or preprocessor ordering conflicts. This would catch regressions early and improve maintainability.
- [ ] Examine existing tests in crates/mdbook-driver/src/mdbook/tests.rs to understand current coverage
- [ ] Create test fixtures in crates/mdbook-driver/tests/ with sample markdown books containing edge cases (circular links, broken includes, etc.)
- [ ] Add integration tests verifying each preprocessor works correctly in isolation and when chained together
- [ ] Test the links preprocessor (crates/mdbook-driver/src/builtin_preprocessors/links/) with various link formats and take_lines configurations
Add missing documentation and examples for the mdbook-core public API
The crates/mdbook-core/README.md exists but is minimal. Given the workspace lint enforces missing_docs = 'warn', there are likely undocumented public functions in crates/mdbook-core/src/book.rs, crates/mdbook-core/src/config.rs, and utilities. Adding comprehensive doc comments with examples would help external crate users and follow the Rust documentation conventions the project claims to enforce.
- [ ] Run 'cargo doc --open' on mdbook-core and identify all public items missing doc comments
- [ ] Add doc comments with at least one example to crates/mdbook-core/src/book.rs (Book struct and key methods)
- [ ] Add doc comments to crates/mdbook-core/src/config.rs explaining Config struct fields and serialization behavior
- [ ] Document utility functions in crates/mdbook-core/src/utils/html.rs and crates/mdbook-core/src/utils/toml_ext.rs with use-case examples
Add CI workflow for testing across multiple Rust versions and MSRV validation
The workspace specifies rust-version = '1.88.0' as the MSRV but the main.yml workflow likely doesn't explicitly test against the MSRV. This is a gap for a library crate (mdbook-core) used by external tools. Adding an MSRV test job in .github/workflows/main.yml would prevent accidental semver-breaking changes to the minimum supported Rust version and catch dependency compatibility issues early.
- [ ] Review .github/workflows/main.yml to confirm it doesn't test against the MSRV (1.88.0)
- [ ] Add a new GitHub Actions job that installs Rust 1.88.0 and runs 'cargo +1.88.0 test --workspace'
- [ ] Test with features combinations relevant to library users (e.g., cargo test --all-features on mdbook-core, mdbook-renderer)
- [ ] Update .github/workflows/main.yml to fail the workflow if MSRV testing fails, making it blocking for PRs
🌿Good first issues
- Add test coverage for crates/mdbook-core/src/utils/html.rs (HTML utility functions)—currently no visible test file, likely missing unit tests for edge cases like malformed HTML tags: easy
- Document the preprocessor plugin interface: add examples/ or guide docs explaining how to write external preprocessors that hook into the mdbook-driver pipeline (cmd.rs shows spawning external binaries, but there's no developer guide): medium
- Implement missing Handlebars helpers or partials for common book layouts—check crates/mdbook-html/ for TODOs or add accessibility features (ARIA labels, skip navigation) to the default theme templates: medium
⭐Top contributors
Click to expand
Top contributors
- @ehuss — 70 commits
- @renovate[bot] — 13 commits
- @github-actions[bot] — 5 commits
- @cobyfrombrooklyn-bot — 2 commits
- @tuyen-at-work — 1 commits
📝Recent commits
Click to expand
Recent commits
9190b5d— Merge pull request #3087 from ehuss/limit-global-keypress (ehuss)4fb647c— Fix global keypress handling with shadow DOM elements (ehuss)c5c31bb— Fix global keypress handler with the ACE editor (ehuss)9ea86e7— Merge pull request #3083 from rust-lang/update-dependencies (ehuss)ae1a431— Merge pull request #3082 from rust-lang/renovate/actions-setup-node-6.x (ehuss)d2f954c— Update cargo dependencies (github-actions[bot])8412c5a— Update actions/setup-node action to v6.4.0 (renovate[bot])4adc4b0— Add a test for global keypress with ACE editor focused (ehuss)22f3035— Add a test for global keypress with shadow-dom elements (ehuss)973a240— Merge pull request #3077 from rust-lang/update-dependencies (ehuss)
🔒Security observations
mdBook's security posture is generally good with proper dependency management and intentional version pinning. The codebase shows awareness of security through workspace lints and organized structure. Main concerns are: (1) XSS risks in HTML rendering pipeline, (2) command injection in external preprocessor support, (3) potential path traversal in file operations, and (4) missing security headers in HTTP serving. The pinned pulldown-cmark dependency shows intentional stability over frequent updates, which is reasonable but requires monitoring. No hardcoded secrets or exposed credentials detected. The codebase would benefit from explicit input validation frameworks and security header configuration in the HTTP server component.
- Medium · HTML Parsing and XSS Risk in HTML Renderer —
crates/mdbook-html/. The mdbook-html crate uses html5ever and handlebars for rendering HTML content. User-supplied markdown content is processed through pulldown-cmark and then rendered via handlebars templates. While pulldown-cmark has HTML escaping, template rendering could potentially allow XSS if user input is not properly escaped in all template contexts. Fix: Ensure all user-supplied content is properly escaped in handlebars templates. Review template files for any use of triple-braces {{{}}} which bypasses escaping. Consider implementing a Content Security Policy (CSP) in generated HTML output. - Medium · Command Execution in External Preprocessors —
crates/mdbook-driver/src/builtin_preprocessors/cmd.rs. The codebase supports external preprocessors via command execution (seen in crates/mdbook-driver/src/builtin_preprocessors/cmd.rs). If user-supplied preprocessor commands or arguments are not properly validated, this could lead to command injection attacks. Fix: Validate and sanitize all preprocessor command names and arguments. Use allowlists for permitted preprocessor commands. Avoid constructing shell commands with user input; use array-based execution with proper argument separation. - Low · File System Path Traversal Risk —
crates/mdbook-core/src/utils/fs.rs. The codebase handles file system operations (crates/mdbook-core/src/utils/fs.rs) for reading markdown and configuration files. Path traversal vulnerabilities could occur if user-supplied paths are not properly validated before file operations. Fix: Implement strict path validation to ensure files are accessed only within the intended book directory. Use canonicalization and ensure resolved paths are within the project root. Reject paths containing '..' or absolute paths outside the project. - Low · Dependency on External Markdown Parser —
Cargo.toml - pulldown-cmark dependency. The project depends on pulldown-cmark (v0.13.3) which is a complex parser. While the version is pinned, future updates should be carefully reviewed for security implications. The dependency comment 'Do not update, part of the public api' suggests intentional version pinning, but this could lead to missing security patches. Fix: Monitor pulldown-cmark security advisories even though version is pinned. Establish a process to evaluate security patches. Consider creating a wrapper or validation layer around markdown parsing for defense-in-depth. - Low · Missing Security Headers in Static HTTP Server —
crates/mdbook-driver/, crates/mdbook-html/. The crate uses axum (0.8.9) for serving content. Default axum configuration may not include security headers like CSP, X-Frame-Options, or X-Content-Type-Options. The live server functionality could serve content without proper security headers. Fix: Configure axum middleware to add security headers (Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, Strict-Transport-Security). Document security considerations for users running mdBook's local server. - Low · No Explicit Input Validation Framework —
crates/mdbook-core/src/config.rs, crates/mdbook-core/src/utils/toml_ext.rs. The configuration parsing (crates/mdbook-core/src/config.rs) uses toml crate for deserialization. While serde provides basic type validation, there may be insufficient validation of sensitive configuration values (paths, URLs, preprocessor names). Fix: Implement comprehensive input validation for all configuration values. Use a dedicated validation library or custom validators for paths, URLs, and command names. Document which configuration values accept user input.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.