The Markdown text format makes it easy to create human-readable text that’s also readily translated into HTML. Originally developed for blogging and message boards, it’s since become widely used as a source format for documentation.
This article reviews four documentation-generation tools—mdBook, Quartz, MkDoc, and HonKit. All support Markdown as their primary source. They can also be used for any other project where you want to translate Markdown into a publishable format, including e-books and PDFs.
Markdown extension support
The core Markdown syntax supports only a small subset of HTML or annotation types, so a culture of extensions and add-ons for Markdown (e.g., GitHub-flavored Markdown) sprung up over time to fill those gaps. Each of the tools in this article has support for different extensions, either natively or by way of plugins. Even fairly exotic requirements like math markup aren’t hard to support with the right Markdown extension.
mdBook
Most projects use an internal tool to generate their docs, and mdBook is a classic example. It’s written in Rust, and the Rust language project uses it to generate documentation like the Rust Programming Language book. However, you don’t need to be proficient in Rust to use mdBook, unless you plan on writing extensions for it. If you just want to use the tool as-is, you can download a precompiled binary and get right to work.
The process for setting up an mdBook project is a little like initializing a new project in Rust or any other modern programming language. You run the mdBook command-line tool—mdbook init
—to generate a new, blank-book project with some minimal pre-filled boilerplate, including a .gitignore
. You can then provide the basic details either interactively or at the command line.
mdBook projects revolve around a SUMMARY.md
file, essentially a table of contents. You use conventional Markdown notation to link to the files in your book, organize them under subheads, and sort them into hierarchies. If you provide links in your SUMMARY.md
to files that don’t yet exist, they will be automatically created and populated with the page title as an H1
subhead when you run the build process on your book.
An example SUMMARY.MD
might look like this:
# Summary
[Introduction](README.md)
---
- [Chapter 1: Installing The Nothing App](./chapter_1.md)
- [Chapter 2: Using The Nothing App](./chapter_2.md)
- [Use Cases](./chapter_2_1.md)
- [Chapter 3: Removing The Nothing App](./chapter_3.md)
- [Manually Deleting User Data](./chapter_3_1.md)
You typically use the build
command to regenerate the book’s HTML on demand, but it’s often more convenient to use watch
to serve the built pages interactively on a local web server. Any changes to the source file automatically rebuild them, so you can see what your documentation looks like in near-realtime as you write it.
If you have code examples in your book, you can automatically generate tests for them. Right now, mdBook only tests Rust code blocks in this way, and you need to supply proper test suites to do it. But there’s clearly room for this feature to extend to other programming languages.
This points up mdBook’s single biggest limitation, that it focuses mainly on documenting Rust projects. The tool can be extended by way of a preprocessor extension system, but you need to know Rust to write such a preprocessor. On the other hand, there is a small list of available third-party plugins. It includes enough support for other things (like LaTeX) to make mdBook worth considering for documenting non-Rust projects.
Quartz
Now in its fourth major revision, Quartz is intended not just for publishing documentation from Markdown but also sharing collections of notes, or what creator Jacky Zhao calls digital gardens. Quartz integrates with the popular Markdown-based note-taking app Obsidian (Obsidian, Quartz—get it?) but any text editor that supports Markdown format will work.
Quartz does not have a standalone binary installer. You can set one up by installing it from source (you’ll need Node.js to run it), or pulling a Docker container. Earlier versions of Quartz were apparently quite complex to set up due to their dependency on the Hugo static-site generator. But version 4 is a complete rewrite.
By default a content
directory in the source tree is where Quartz looks for Markdown source files. Also, Quartz depends on a configuration file in the program directory for describing the site‘s configuration and layout. This makes it hard to use a single Quartz source installation to build multiple sites with different configurations and layouts.
Documents in Quartz have what’s called front matter to hold metadata. Front matter metadata can be customized with plugins, but the default supported metadata is fine for most projects. Here’s an example with document content:
---
title: A Typing Test
draft: false
tags:
- qwerty
---
Jackdaws *love* my big sphinx of **quartz**!
Note that any links you create in a Markdown document will not automatically have a target created for it when you build the site; those links go to a 404 page.
One truly wonderful aspect of Quartz is how much rich, powerful, reader-facing functionality is baked into the product. Backlinks, breadcrumbs, callouts, and popover previews can all be generated automatically or programmatically from your Markdown. LaTeX and Mermaid diagram support also come packed in, along with powerful user-facing features like type-to-search and single-page app routing to avoid flashes of unstyled content when navigating. You can also author your own plugins in TypeScript.
MkDocs
Built with Python, MkDocs is one of the simpler Markdown documentation generators out there. It doesn’t have many core features, but it’s massively extensible through a rich plugin ecosystem.
MkDocs does not have a standalone installer but runs from within a Python environment, and can be set up there with pip install mkdocs
. It does, however, provide a command-line tool, available in the Python environment, to run the program and issue commands. mkdocs new
creates a new, minimal documentation project in the provided directory, and mkdocs serve
runs a local web server to display the documentation project in the current directory.
New MkDocs projects start with two files: index.md
(the table of contents) and an mkdocs.yml
configuration file. (You can also use README.md
as your index file.) The config file provides metadata for the document project as well as how to organize its files into a table of contents. For example:
nav:
- Home: index.md
- User Guide:
- Writing your docs: writing-your-docs.md
- Styling your docs: styling-your-docs.md
- About:
- License: license.md
- Release Notes: release-notes.md
If you don’t provide a nav:
block, MkDocs will automatically create one by auto-discovering all the .md
files in the documents directory, sorted by filename.
A few crucial things are built right in. Type-to-search, a staple of good documentation, comes included by way of the lunr.js project. It exposes some tunable options, such as whether to pre-index the site or not (a good idea for large sites). The supported flavor of Markdown includes a few extensions by default, such as tables and code highlighting. Metadata for documents can follow Quartz’s front matter format, or use what’s called the MultiMarkdown metadata style. You can use either style interchangeably in the same project, although which metadata keys are supported depends on the theme you’re using to render the docs.
MkDocs’s small core functionality is offset enormously by its giant ecosystem of plugins and auxiliary projects: Themes, document generation from APIs, graphics and charts, code interaction and execution (e.g., in-line Jupyter notebooks), and further extensions for Markdown are just a few categories of what’s included.
HonKit
Some readers may be familiar with Gitbook, a commercial document-hosting service with an open source rendering front end. HonKit is a fork of the original Gitbook project (circa 2018) and highly compatible with the original, but with its own development team. HonKit is also more liberally licensed, as it uses Apache while Gitbook’s open source bits are GNU GPL 3.
HonKit’s core functionality is minimal but well-chosen. It works as both a Node.js library and command-line tool for generating documentation sites from Markdown or AsciiDoc files. Once you’ve used npm
to install HonKit (either globally or locally), you can us npx honkit
to access its commands: init
to set up a new blank book; serve
to preview the book locally; and build
to render the output. PDF, ePub, and Mobi-format output are all included without additional plugins, and you can even include cover art automatically.
Markdown files can use YAML-style front matter, as per Quartz, and the variables defined there can be used in your own templating. HonKit supports a basic but useful set of Markdown features, including tables, code blocks with common syntax highlights, and simple footnotes.
The only file required to create a new HonKit book is a README.md
, which serves as an introduction. A table of contents (SUMMARY.md
), written in an outline-level style, is optional, as is JSON
-based configuration data for the book. The latter can contain a great many granular details: file paths, publication details, even which version of the program was used to render the output.
Hundreds of plugins exist for both Gitbook and HonKit. HonKit can work with both types of plugins interchangeably, so it’s not hard to expand its base functionality for conceivably any documentation job, especially those with Git- and GitHub-based integrations.
Conclusions
For any Rust or Rust-adjacent project, mdBook is a no-brainer, since it’s written in the Rust language and was designed to generate docs for Rust projects. But it’s also useful for those who want a download-and-go doc-generation experience. Quartz uses Node.js, so unless you’re already writing Node apps it requires a little more heavy lifting to get going, but it packs in a truly staggering amount of native functionality. MkDocs requires Python as a dependency and is highly minimal at its core, but its plugin ecosystem is tremendous. Moreover, any Python user can extend MkDocs by simply using it as a library. And, while HonKit is also minimal (and also requires Node.js), it features a gigantic third-party ecosystem thanks to it being a fork of Gitbook.