Switching From Sphinx to MkDocs Documentation — What Did I Gain and Lose?
Guide on performing this switch, and a comparison between them
“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:
- Technical documentation: Describing the technical aspects of the project’s inner workings, it can be process documentation or product documentation
- 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.
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.
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.
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
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!
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.
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
andimg
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).
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
- Official Documentation: https://www.sphinx-doc.org/
- Immaterial Documentation (theme): https://jbms.github.io/sphinx-immaterial/
- Code block example: https://sublime-and-sphinx-guide.readthedocs.io/en/latest/code_blocks.html
- Code animation example: https://pypi.org/project/sphinx-term/
MkDocs
- Official Documentation: https://www.mkdocs.org/
- Material Documentation (theme): https://squidfunk.github.io/mkdocs-material/getting-started/
- mkdocstrings Documentation (for Python docstring): https://mkdocstrings.github.io/python/
- Termynal Documentation (code animation): https://mkdocs-plugins.github.io/termynal/