avatarKay Jan Wong

Summary

The author discusses the transition from Sphinx to MkDocs for project documentation, detailing the gains and losses in features and ease of use.

Abstract

The article "Switching From Sphinx to MkDocs Documentation — What Did I Gain and Lose?" provides a comprehensive comparison between two popular documentation tools: Sphinx and MkDocs. The author, having used both, shares insights into the setup process, ease of use, and the aesthetic and functional advantages of MkDocs, such as a nicer overall layout, better navigation, and the inclusion of social media links. However, the transition was not without drawbacks, including the loss of RST file support and the inability to perform doctest and coverage tests within MkDocs. The author also highlights the versatility of both tools in hosting documentation on platforms like Read the Docs and GitHub Pages. Despite the challenges, the author concludes that MkDocs, with its Material theme, offers a more user-friendly and hassle-free experience for creating and maintaining documentation.

Opinions

  • The author finds MkDocs Material's layout more appealing and subjectively defines "nice" in terms of readability and user-friendliness.
  • MkDocs is praised for its ease of setup and use, particularly due to its live server feature and the simplicity of its configuration file.
  • The author expresses a preference for MkDocs' code block and code animation features, considering them more polished and engaging compared to Sphinx's offerings.
  • MkDocs' navigation system, with its tabs and scrolling table of contents, is highly regarded for its intuitiveness and efficiency.
  • The inclusion of social media links and social cards in MkDocs is seen as a valuable feature for enhancing the documentation's reach and accessibility.
  • The author notes a significant inconvenience in having to convert RST files to Markdown during the transition to MkDocs.
  • The loss of doctest and coverage test features in MkDocs is acknowledged as a disadvantage, though the author suggests alternative tools for these purposes.
  • Both Sphinx and MkDocs are recognized for their ability to be hosted on Read the Docs and GitHub Pages, with MkDocs requiring minimal configuration changes for deployment.
  • The author recommends MkDocs for its out-of-the-box aesthetics and reduced need for CSS customization, despite the initial effort required to switch from Sphinx.

Switching From Sphinx to MkDocs Documentation — What Did I Gain and Lose?

Guide on performing this switch, and a comparison between them

Photo by melanfolia on Unsplash

A project is only as good as its documentation” — a quote from my earlier 3-part article series stressing the importance of documentation. I have since learned that there are different kinds of documentation, the more common ones being:

  1. Technical documentation: Describing the technical aspects of the project’s inner workings, it can be process documentation or product documentation
  2. Business documentation: Describing what business problems it solves or business objectives met

There exists a type of documentation that is kind of in-between, these are manuals, guides, and tutorials. This is especially important if you want technical users to work with or use your project, or business users to understand your project and get buy-ins.

As the documentation gets more complex with more content, it can be tricky to display it in a user-friendly and readable format. For example, the tutorials should not be embedded within the technical documentation, and there should ideally be a separate navigation tab or section between them.

This sparked me to explore more Sphinx themes to make my documentation prettier and to be able to handle more information. I ended up being drawn to Sphinx-Material and Sphinx-Immaterial themes which implement the Material theme from MkDocs. After a lot of tweaking, and still not getting the results I wanted, I switched to MkDocs and finally understood the hype about MkDocs.

Having tried various documentation methods and themes, I will try to compare them — focusing on the features gained and lost from switching from Sphinx to MkDocs. Finally, this article will end with important MkDocs settings to incorporate for more optimal documentation!

Note: If interested, this is the link to my documentation made with the Sphinx-Material theme, and this is the link to the same documentation made with MkDocs :)

Table of Contents

Sphinx vs. MkDocs

Features Gains from MkDocs

Features Lost from MkDocs

Similar Features

Important MkDocs Settings

Sphinx vs. MkDocs: Setting Up

Both methods are similar — both require installing a Python package and having a one-liner for installation and subsequent deployment of documentation

For Sphinx, these are the commands for installation, setup, and generation of documentation respectively.

$ pip install sphinx

$ mkdir docs
$ cd docs
$ sphinx-quickstart

$ make html

Within the docs folder, there is a build folder which contains the generated HTML files, and a source folder which contains the configuration and source files for the documentation. Configuration is set with docs/source/conf.py Python file.

For MkDocs, these are the commands for installation, setup, and generation of documentation respectively.

$ pip install mkdocs

$ mkdocs new .

$ mkdocs serve      # deploy locally
$ mkdocs gh-deploy  # deploy to GitHub Pages

Within the docs folder, there is only one index.md file which is the initial documentation. In the root folder, there is a mkdocs.yml YAML file that controls the configuration, and generated HTML files are stored in the site folder.

Sphinx vs. MkDocs: Ease of Use

MkDocs is easier to use — especially if you are still setting up various configuration

For Sphinx, any change to the configuration and code docstrings will require running the make html command again, making it cumbersome and the wait can be long depending on the number of HTML pages being generated.

MkDocs is easier to use as changes to the configuration and Markdown files are automatically refreshed since a server is used to host the documentation upon running mkdocs serve. However, changes to the code docstrings will require restarting the server as these files are not being watched for changes.

Features Gained: Nicer Overall Layout

MkDocs Material has a prettier layout with some tweaking

Before elaborating on my point, I must preface that while nice is subjective, I will try to define it more objectively. Also, some features that I mentioned that MkDocs have that are missing in Sphinx could be achieved in some Sphinx themes or a Sphinx extension — do comment if you have a good Sphinx alternative! :)

The purpose of documentation should be to make it understandable for the end-users. With this consideration in mind, having a readable layout is important.

While further customizations are available using CSS (more on this later), certain layouts are hard to fix with CSS. For example in Fig 1 below, MkDocs integrates with black to perform formatting and displays the function signature in a more readable way than Sphinx.

Fig 1: Code Argument display on MkDocs (top) and Sphinx (bottom) — Image by author

Still on the topic of code formatting, in MkDocs, the plugin mkdocstrings allows the interpretation of Python codes and handles the display and format of Python codes by configuring it in the mkdocs.yml file. I do not think it is as straightforward in Sphinx as I would either have to find a theme or an extension that already implements this, or modify the CSS to my needs. In my experience, I was using multiple extensions such as autodoc and autodocsumm, and each extension had its own setting which could get messy and confusing.

Although there is a larger user base and more community support for Sphinx, I find the documentation for certain Sphinx themes and plugins harder to understand (ironically) due to a lack of examples, and good themes are hard to search for unless you already know what you are looking for.

Fig 2: Code blocks (top) and code animation (bottom) in MkDocs — Image by author

Another feature in layout that I like about MkDocs is code blocks and code animation! With code blocks, codes can be segmented into tabs and take up less scrolling visual space. Code blocks are considered a Markdown extension, so it is achieved by simply specifying the extension in the mkdocs.yml file and just following the Markdown format to achieve this.

Code animation makes the code more engaging by simulating typing or download speed. This is achieved with a plugin called Termynal, similarly, install the Python package, add it to the configuration file, and follow the Markdown format.

When writing this article, I tried to find a Sphinx alternative for these features (since now I know what I am searching for) and found an extension sphinx-term that does the same for code animation. For code blocks, it is rendered such as Fig 3 below, which does not look as polished as MkDocs.

Fig 3: Code animation in Sphinx — Image from the documentation

From this article, Sphinx is more mature and has more followers, themes, and plugins than MkDocs. I believe if I look hard enough, maybe I can find the Sphinx theme and plugin that I am looking for. However, they may not be as configurable as I like, or look the way I want, and I have to spend extra hours customizing the CSS. The efforts of customizing CSS might be wasted once you change the theme (like I did). Minimizing the need for CSS tweaks, the MkDocs Material theme looks better off the shelf which makes the documentation process more hassle-free. In addition, most of the enhancements for MkDocs can be tuned with the configuration file, reducing the need for CSS as well.

Features Gained: Better Navigation

MkDocs Material navigation is available at the top panel, left and right sidebar

Fig 4: Navigation on MkDocs — Image by author

Referencing Fig 4 above, the navigation to different pages at the top panel is considered navigation tabs, the navigation at the left sidebar is considered navigation sections, and the navigation the the right sidebar is considered the table of contents (or toc).

The navigation tabs allow me to separate distinct categories of my documentation into different tabs, while the navigation section allows my documentation to be further sectioned and organized. What I like most is that the table of contents scrolls together with the user, and the earlier sections will be greyed out once it is past. This is also achievable with the Sphinx Material and Immaterial theme (not all themes!), but I just thought this was a pretty neat feature.

If still unsatisfied, MkDocs Material has informative documentation showing the different navigation settings available, for example, the left sidebar can be integrated with the right sidebar, the sidebars can be hidden on selective pages, or the sidebar can be made collapsible, and much more.

That being said, this navigation layout is theme-dependent on both Sphinx and MkDocs — and my inclination towards Material theme (available on both Sphinx and MkDocs) might make me biased towards this form of navigation.

Features Gained: Socials

Link to other social media platforms!

Fig 5: Socials on MkDocs — Image by author

Although this is theme-dependent (again), upgrading the Material theme from Sphinx to MkDocs allowed me to specify links to my other social media platforms such as GitHub, LinkedIn, and Medium. This can be a trivial feature, but it is still a feature I appreciate.

Fig 6: Social card on MkDocs — Image by author

Another feature gained is social cards, which are enabled by default. Social card is the large thumbnail displayed when sharing your documentation URL (Fig 6) and social cards from different pages of documentation look different as it infers from the page title! However, in smaller thumbnails, the image will be cut off, such as in the example URL below.

That being said, these are considered features gained from MkDocs because the Material theme on Sphinx is not maintained anymore. The Immaterial theme on Sphinx is still maintained and has more features (it has this social feature!). However, having tried both Material and Immaterial themes for Sphinx, I felt the font, alignment, layout, or overall feel is better with Material (which has fewer features) and I did not want to overly customize CSS to work with Immaterial (despite having more features). To each his/her own, but I did not like this tradeoff between the Sphinx themes.

I have been singing praises about MkDocs so far, now for the bad parts…

Features Lost: Ability to use RST files

MkDocs supports Markdown only, Sphinx can support Markdown and RST files

This is probably the biggest contrast between Sphinx and MkDocs — the ability to use RST files. It is not a deal breaker, nor am I saying RST files are better than Markdown files. It made the transition from Sphinx to MkDocs more tedious than necessary as I had to rewrite my .rst files to .md files. The biggest difference between the formats would be when I was converting:

  • Tables (Tables in Markdown are more readable in raw format than RST)
  • Font headings (Specifying H1/H2 etc. fonts take up less visual space in Markdown than RST)
  • Links and Images (a and img tags are represented differently)
  • Link to code module (mainly switching from .. RST notation to :: Markdown notation)

This probably took the bulk of the time when I was switching from Sphinx to MkDocs. Since Sphinx can also work with Markdown files (with the myst_parser plugin), Markdown files are more versatile which makes this switch worthwhile.

Features Lost: Doctest and Coverage Tests

Only Sphinx can run documentation tests

Doctest helps to test the codes in docstrings if they are working as expected, it is similar to performing unit tests for code, but this is unit tests for docstrings. For example in the code block below, doctest will test if the code example func_add(1, 2) will return a result of 3. This is useful as it ensures the documentation examples remain valid and relevant after your code is written or modified.

def func_add(x, y):
    """Add two numbers

    Examples:
        >>> func_add(1, 2)
        3

    (other documentation below)
    """
    return x + y

While coverage tests for code check if unit tests can reach all lines of code, coverage tests for documentation check if every class and function has docstrings written for it. This is useful to ensure that all modules are documented (although quality is undetermined).

Fig 7: Results of Doctest (left) and Coverage test (right) on Sphinx — Image by author

Doctest and coverage tests on Sphinx are enabled with the extensions sphinx.ext.doctest and sphinx.ext.coverage respectively. After running the commands to run the respective tests, the results are shown in Fig 7 above. Although these doctest and coverage tests are separate commands and do not automatically run on make html, they are still useful to quickly check if any module has missing or invalid docstrings.

I cannot find any working MkDocs alternatives for these tests. Considering Python module alternatives, docstr-coverage can run coverage tests in the way Sphinx does it. doctest can run doctest, however, it cannot be called from the command line to run for the whole project at once. For now, I am keeping Sphinx setup in my project just to benefit from these tests.

Similar Features: Host on Read the Docs and GitHub Pages

Read the Docs and GitHub Pages support both types of documentation

Read the Docs is a platform to host documentation for free. Before the switch, I was worried that Read the Docs only supported Sphinx, but I realized modifying two lines in the .readthedocs.yml file allowed me to switch between deploying Sphinx and MkDocs!

# For Sphinx
sphinx:
  - configuration: docs/source/conf.py

# For MkDocs
mkdocs:
  - configuration: mkdocs.yml

For my project, I also enabled documentation to be built on GitHub pages, automated through GitHub actions. The changes to the GitHub workflow steps are captured below.

# For Sphinx
- name: Install dependencies
  run: |
    pip install -r docs/requirements.txt
- name: Sphinx build
  run: |
    sphinx-build docs/source docs/build
- name: Deploy to GH Pages
  uses: peaceiris/actions-gh-pages@v3
  with:
    publish_branch: gh-pages
    github_token: ${{ secrets.GITHUB_TOKEN }}
    publish_dir: docs/build/
    force_orphan: true

# For MkDocs
- name: Install dependencies
  run: |
    pip install -r docs/requirements.txt
    git config user.name 'github-actions[bot]' && git config user.email 'github-actions[bot]@users.noreply.github.com'
- name: Deploy to GH Pages
  run: mkdocs gh-deploy

Bonus: Search Engine Optimization

Make your documentation more discoverable by search engines with meta tags

Meta tags are HTML tags that provide additional information about a page to search engines. The MkDocs documentation mentioned that there can be page overrides in the form of HTML files to modify or inject your own HTML elements, in this case, meta tags, into the layout.

Below were the changes made to my main.html override file and mkdocs.yml configuration file that allowed me to add meta tags to my website. These changes were not immediately intuitive from the documentation, and I adapted from this GitHub issue comment.

<!-- In docs/overrides/main.html -->

{% extends "base.html" %}

{% block site_meta %}
<meta name="..." content="...">
<meta property="..." content="...">
{{ super() }}
{% endblock %}
# In mkdocs.yml
theme:
  custom_dir: docs/overrides

Good documentation goes a long way, and tools like Sphinx and MkDocs make the documentation more readable, while platforms like GitHub pages and Read the Docs make documentation more accessible. I hope this article gave a good head start on adopting MkDocs and up your documentation game!

Related Links

Sphinx

MkDocs

Documentation
Mkdocs
Mkdocs Material
Sphinx
Tips And Tricks
Recommended from ReadMedium