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
-
New Slimbook EVO with Raw AMD Ryzen Power
If you're looking for serious power in a 14" ultrabook that is powered by Linux, Slimbook has just the thing for you.
-
The Gnome Foundation Struggling to Stay Afloat
The foundation behind the Gnome desktop environment is having to go through some serious belt-tightening due to continued financial problems.
-
Thousands of Linux Servers Infected with Stealth Malware Since 2021
Perfctl is capable of remaining undetected, which makes it dangerous and hard to mitigate.
-
Halcyon Creates Anti-Ransomware Protection for Linux
As more Linux systems are targeted by ransomware, Halcyon is stepping up its protection.
-
Valve and Arch Linux Announce Collaboration
Valve and Arch have come together for two projects that will have a serious impact on the Linux distribution.
-
Hacker Successfully Runs Linux on a CPU from the Early ‘70s
From the office of "Look what I can do," Dmitry Grinberg was able to get Linux running on a processor that was created in 1971.
-
OSI and LPI Form Strategic Alliance
With a goal of strengthening Linux and open source communities, this new alliance aims to nurture the growth of more highly skilled professionals.
-
Fedora 41 Beta Available with Some Interesting Additions
If you're a Fedora fan, you'll be excited to hear the beta version of the latest release is now available for testing and includes plenty of updates.
-
AlmaLinux Unveils New Hardware Certification Process
The AlmaLinux Hardware Certification Program run by the Certification Special Interest Group (SIG) aims to ensure seamless compatibility between AlmaLinux and a wide range of hardware configurations.
-
Wind River Introduces eLxr Pro Linux Solution
eLxr Pro offers an end-to-end Linux solution backed by expert commercial support.