Building project documentation from Markdown files
Documentation, Please
MkDocs, a static site generator, lets you easily transform Markdown files into ready-to-use, user-friendly project documentation.
Documentation: Everybody needs it, but not everyone wants to deal with it, especially for smaller projects where time and resources are limited. Even if you manage to find time to create technical content, turning it into user-friendly, searchable, and easy-to-navigate documentation is no mean feat – unless you use MkDocs [1]. This unassuming tool is manna from heaven for anyone looking for a straightforward and low effort way to publish and maintain documentation (Figure 1). You can also use MkDocs for any content that needs to be presented in a structured and easily searchable format, from research notes to a knowledge base.
First Steps
If you have Python 3 and pip installed on your machine, you can deploy MkDocs by running the following command as root:
pip3 install mkdocs
While you are at it, you can also install the Material theme [2] with:
pip3 install mkdocs-material
Although technically correct, to call Material a theme would be doing it a great disservice. Instead of merely giving MkDocs a new look, Material adds an entire new level of functionality, making it worth installing for that reason alone. While certain capabilities of Material are available only to paying supporters, all the features described in this article are free.
When you are ready to create your first documentation project, run the command
mkdocs new documentation
(replace documentation
with your project name). This creates a project skeleton that includes two items: the mkdocs.yml
configuration file and the docs
directory for storing the actual content. The content in this case is Markdown-formatted files, and it's up to you how to organize them inside the directory. For example, you can create a separate file for each topic and then group the files into subdirectories, such as Getting started, Tutorials, References, etc. Want to quickly preview the documentation you're working on? Switch to the created project directory, run the mkdocs serve
command, and point the browser to 127.0.0.1:8000. The clever part is that whenever you edit the files in the project directory, the server automatically rebuilds the content to reflect the changes.
While the built-in server allows you to preview the documentation site, you still need to convert raw source into a self-contained publishable static site. When you're ready to publish the documentation, run the mkdocs build
command, and MkDocs creates the site
directory containing the static pages and all the required components. You can then either upload the contents of the site
directory to your server or use MkDocs to deploy documentation on GitHub (more about that later). That's what the most basic MkDocs workflow looks like: Create a project skeleton, populate the docs
directory with Markdown-formatted text files, preview the result in the browser, and use the mkdocs build
command to generate ready-to-publish static documentation.
Configuration
MkDoc's default configuration does the job, but it only uses a fraction of the available features. To make use of these features lurking beneath the surface, you need to enable and configure them by editing the mkdocs.yml
configuration file. Initially, the file contains a single configuration parameter: site_name: My Docs
. Listing 1 shows a real world configuration file. The first four parameters (site_name
, site_description
, site_author
, and site_url
) are pretty much self-explanatory.
Listing 1
Sample Configuration File
site_name: KOReader compendium site_description: KOReader knowledgebase site_url: https://dmpop.github.io/koreader-compendium/ site_author: Dmitri Popov repo_url: https://github.com/dmpop/koreader-compendium/ edit_uri: blob/main/docs/ copyright: Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) plugins: - search - git-revision-date-localized: enable_creation_date: true type: date theme: name: material logo: logo.png favicon: logo.png palette: - scheme: default primary: green accent: teal toggle: icon: material/lightbulb-outline name: Switch to dark mode - scheme: slate primary: green accent: teal toggle: icon: material/lightbulb name: Switch to light mode font: text: Lato code: JetBrains Mono markdown_extensions: - admonition - pymdownx.details - pymdownx.highlight: linenums: true - pymdownx.superfences - pymdownx.inlinehilite - pymdownx.keys
Things get a bit more interesting starting with the repo_url
parameter. MkDocs assumes that you manage your documentation project's source code using Git. You don't have to use Git, but if you choose this approach and opt to use GitHub or GitLab public or private instances for hosting the source code, you can specify the URL of the repository. This adds the link in the upper-right corner of the finished documentation site. If you use GitHub, MkDocs even adds Stars and Forks counters. But that's not all. If you want to encourage readers to contribute to the documentation, specify edit_uri
to add an edit link to each page. This link points to the page in the GitHub repository where the reader can make edits and create pull requests. The exact URL depends on the platform you're using. For GitHub, it's blob/main/docs/
; for GitLab, it's -/blob/main/docs
(where main
is the name of the branch).
The copyright
parameter requires no explanation, so I'll move on to the plug--ins
section. MkDocs' functionality can be extended by installing plugins. I'll discuss third-party plugins later, but what you need to know now is that to enable a plugin you must specify it in the plugins
list. The search
plugin is enabled by default, but you must add it to the list if you use other plugins.
MkDocs comes with a handful of themes, and you can specify the desired theme in the theme
section. Because you've installed Material, it makes sense to enable it for use with MkDocs. It also makes sense to replace the default logo and favicon with your own. To do this, specify their paths and file names as the logo
and favicon
parameters. In Listing 1, the logo.png
file is used both as a logo and a favicon, and the file itself is stored in the docs
directory.
Material comes with its own features that can be enabled by adding them to the features
list. For example, if you want the header bar to automatically hide when the user scrolls past a certain threshold, enable header.autohide
as follows:
features: - header.autohide
Material makes it possible to adjust its color palette by specifying primary and accent colors using the appropriate entries under the palette
parameter. To quickly figure out what colors you want to use, open the Changing the colors page [3] and pick the desired primary and accent colors to see the result in real time. A dark mode with the ability to toggle it makes the reading experience more comfortable. To enable this feature in Material, you have to specify a dark mode theme in addition to the default (light) one and then define toggles for each theme. In Listing 1, the toggle for the default theme is as follows:
- scheme: default <...> toggle: icon: material/lightbulb-outline name: Switch to dark mode
And the toggle for the dark theme looks like this:
- scheme: slate <...> toggle: icon: material/lightbulb name: Switch to light mode
In the example, slate
is used as the dark theme.
You can also replace the default font. Using the font
list, you can specify any font available through Google Fonts:
font: text: Lato
And if you want to use a specific monospaced font for code, you can do that too:
font: text: Lato code: JetBrains Mono
If you want to bypass Google Fonts and use the fonts you include with your documentation, you can do that by specifying a custom CSS stylesheet:
extra_css: - css/extra.css
Then add a font definition to the extra.css
file:
@font-face { font-family: "Lato"; src: "fonts/Lato.ttf"; }
What makes Material particularly suitable for technical writing is the fact that it supports a wide range of Python Markdown extensions. The admonition
extension, for example, makes it possible to add notes, tips, examples, quotes, warnings, etc. To enable the desired extension, add it to the markdown_extensions
list:
markdown_extensions: - admonition
The extensions you choose to enable depend entirely on your needs. The Python Markdown Extensions page [4] provides a list of all the supported extensions, with detailed descriptions and usage examples. The extensions listed in Listing 1 are the bare minimum that you would want to include. In addition to admonition
, Listing 1 enables syntax highlighting (pymdownx.highlight
), both inline (pymdownx.inlinehilite
) and fenced code blocks (pymdownx.superfences
), as well the ability to render keys and keyboard shortcuts (pymdownx.keys
).
MkDocs Plugins
While MkDocs and Material make a rather powerful combination, you can also add other features and capabilities using MkDocs plugins. Need to add an RSS feed to your documentation site? There is a plugin for that. Want to include charts? There is a plugin for that, too. Similar to MkDocs itself, most plugins are available through the PyPI package repository [5]; to see a list of MkDocs plugins, simply search for mkdocs. To deploy a plugin, install it using the pip package manager. For example, the following command installs the plugin that adds the localized date of the last modification date to every page:
sudo pip3 install mkdocs-git-revision-date-localized-plugin
Once the plugin has been installed, enable and configure it in the configuration file:
plugins: - git-revision-date-localized: enable_creation_date: true type: date
Another plugin worth adding right from the start is Awesome Pages. By default, MkDocs arranges pages alphabetically, which is rarely how you'd want to organize your content. An ugly workaround is to prepend pages with numbers (e.g., 01_quickstart.md
, 02_advanced_config.md
). But if you have a lot of pages and often add new content, keeping the content structured can quickly become a time-consuming and laborious process. The Awesome Pages plugin provides an elegant solution to the problem. Install the plugin using the command
sudo pip3 install mkdocs-awesome-pages-plugin
and add awesome-pages
to the plugins
list in mkdocs.yml
. Then create a .pages
file in the docs
directory and add the pages in the order you want them to appear in the documentation as follows:
nav: - quickstart.md - advanced_config.md
Check the plugin's documentation for other options you can use [6].
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
ESET Discovers New Linux Malware
WolfsBane is an all-in-one malware that has hit the Linux operating system and includes a dropper, a launcher, and a backdoor.
-
New Linux Kernel Patch Allows Forcing a CPU Mitigation
Even when CPU mitigations can consume precious CPU cycles, it might not be a bad idea to allow users to enable them, even if your machine isn't vulnerable.
-
Red Hat Enterprise Linux 9.5 Released
Notify your friends, loved ones, and colleagues that the latest version of RHEL is available with plenty of enhancements.
-
Linux Sees Massive Performance Increase from a Single Line of Code
With one line of code, Intel was able to increase the performance of the Linux kernel by 4,000 percent.
-
Fedora KDE Approved as an Official Spin
If you prefer the Plasma desktop environment and the Fedora distribution, you're in luck because there's now an official spin that is listed on the same level as the Fedora Workstation edition.
-
New Steam Client Ups the Ante for Linux
The latest release from Steam has some pretty cool tricks up its sleeve.
-
Gnome OS Transitioning Toward a General-Purpose Distro
If you're looking for the perfectly vanilla take on the Gnome desktop, Gnome OS might be for you.
-
Fedora 41 Released with New Features
If you're a Fedora fan or just looking for a Linux distribution to help you migrate from Windows, Fedora 41 might be just the ticket.
-
AlmaLinux OS Kitten 10 Gives Power Users a Sneak Preview
If you're looking to kick the tires of AlmaLinux's upstream version, the developers have a purrfect solution.
-
Gnome 47.1 Released with a Few Fixes
The latest release of the Gnome desktop is all about fixing a few nagging issues and not about bringing new features into the mix.