Markdown vs reStructuredText for teaching materials

Featured image: Brandi Redd | Unsplash (photo)

Back in summer 2017. I wrote an article explaining why we used Sphinx and reStructuredText for producing teaching materials and not a wiki. In addition to recommending Sphinx as the solution to use, it was general praise for generating static HTML files from Markdown or reStructuredText.

This summer I made the conversion of teaching materials from reStructuredText to Markdown. Unfortunately, the automated conversion using Pandoc didn’t quite produce the result I wanted so I ended up cooking my own Python script that converted the specific dialect of reStructuredText that was used for writing the contents of and fixing a myriad of inconsistencies in writing style that accumulated over the years.

reStructuredText as the obvious choice for the software documentation

I personally preferred to write reStructuredText, which I found to be more powerful and better standardized than Markdown (I have heard the same is true about AsciiDoc though I haven’t personally used it). When we forked rDock to start RxDock, reStructuredText and Sphinx were the obvious choices for its documentation. A good argumentation why would a software developer prefer reStructuredText over Markdown for software documentation is given in a very fine article written by Victor Zverovich. He mentions two main advantages, the first one being:

reStructuredText provides standard extension mechanisms called directives and roles which make all the difference. For example, you can use the math role to write a mathematical equation (…) and it will be rendered nicely both in HTML using a Javascript library such as MathJax and in PDF via LaTeX or directly. With Markdown you’ll probably have to use MathJax and HTML to PDF conversion which is suboptimal or something like Pandoc to convert to another format first.

(For what it’s worth, this has now been addressed by PyMdown Extension Arithmatex, which is easy to enable when using MkDocs with Material theme.)

The second advantage mentioned by Zverovich is very useful for software documentation and a feature that would be only nice to have elsewhere:

In addition to this, Sphinx provides a set of roles and directives for different language constructs, for example, :py:class: for a Python class or :cpp:enum: for a C++ enum. This is very important because it adds semantics to otherwise purely presentational markup (…)

Markdown as the obvious choice elsewhere

Despite recommending reStructuredText for software documentation, Victor opens his blog post with:

In fact, I’m writing this blog post in Markdown.

It’s the obvious choice for blogs hosted on GitHub Pages since it offers the Markdown to HTML conversion using Jekyll. You don’t have to care how the conversion is done so you can worry about writing the contents. However, the same feature isn’t available for reStructuredText and AsciiDoc as Jekyll supports neither of the two.

Is GitLab any different from GitHub? GitLab Pages supports almost anything you can imagine thanks to GitLab CI/CD, including Sphinx. However, the same isn’t the case for project wikis where GitLab supports Markdown and AsciiDoc, but not reStructuredText (it has been requested 5 years ago).

And it’s a similar story elsewhere. Reddit? Markdown. Slack and Mattermost? Both Markdown. Visual Studio Code supports Markdown without any extensions (but there are 795 of them available if you feel that something you require is not there, compared to 21 for reStructuredText). Finally, it’s a very popular choice among my colleagues and students, which is expected as there is nothing like HackMD for reStructuredText or AsciiDoc that I know of.

Obviously, many of these tools weren’t around when we switched to Sphinx back in 2014. However, now that they are here to stay, Markdown is starting to look like a better choice among the two.

Moving from reStructuredText to Markdown for teaching materials

In my particular case, the straw that broke the camel’s back and made me decide to convert the teaching materials from reStructuredText to Markdown was the student contribution of ZeroMQ exercises for the Distributed systems course (not included yet). I asked the student to write reStructuredText, but got the materials in Markdown and I can understand why is that. Let’s say that the student wanted to do things properly in reStructedText and Sphinx. The procedure is this:

  1. Git clone the repository.
  2. Open the folder in your favorite editor, say VS Code, notice it doesn’t highlight rST out of the box, no problem there is the extension, right?
  3. Install the reStructuredText extension (homepage), close all NotImplemented exception notes that appear when opening the project.
  4. Open a file just the get the feeling of how rST should look. Try to preview it. Unknown directive type “sectionauthor”. Never mind, it’s just one command that is unsupported.
  5. The source code blocks aren’t highlighted neither in the edit nor in the preview pane. Oh well, it’s not a show stopper.
  6. Well, there are more errors in the preview. Never mind, the compile is the real preview. Let’s compile things every time something is changed.
  7. (…)
  8. Send the changes by e-mail or git add, git commit, and git push.

Compare that with the Markdown workflow:

  1. Git clone the repository.
  2. Open the folder in VS Code and start writing.
  3. Send the changes by e-mail or git add, git commit, and git push.

To be fair, VS Code Markdown preview is not rendering Admonitions, but that’s how it goes with the language extensions. Still, it’s much easier to get started with Markdown and MkDocs than with reStructuredText and Sphinx if you are new to documentation writing, which is the case with most of the students.

There are a number of other things I like:

  • Material theme for MkDocs is awesome. It’s a set of extensions in addition to a good looking theme.
  • Integrated search is designed as “find as you type” and provides a much better user experience.
  • Much faster building. It takes 11 seconds to build the group website with MkDocs, while it took 37 seconds to build the older version of the same website with Sphinx.
  • Builtin GitHub Pages deployment functionality. It’s possible to do the same with Sphinx, but it’s much nicer to have it builtin and maintained.
  • Automatic building of the sitemap. (There’s an extension for Sphinx that does the same.)

Overall, I am very satisfied with the results and I’m looking forward to using Markdown for writing teaching materials in the future. I’ll continue to write RxDock documentation in reStructuredText since fancy cross-references and numbered equation blocks are very easy to do in reStructuredText. In addition, there is an official way to produce PDF output via LaTeX, which is quite important to have for proper scientific software documentation. Also, the potential contributors, in this case, are somewhat experienced with documentation tools and can usually find their way around with reStructuredText and Sphinx so it’s not that much of an issue.

Fly away, little bird

Featured image: a-shuhani | Unsplash (photo)

The last day of July happened to be the day that Domagoj Margan, a former student teaching assistant and a great friend of mine, set up his own DigitalOcean (note: affiliate link) droplet running a web server and serving his professional website on his own domain For a few years, I was helping him by providing space on the server I owned and maintained, and I was always glad to do so. To understand why, let’s start the story a little before those times.

During the early years of Mozilla (video recording of my 2015 talk in Croatian, a really nice article at ExtremeTech), I would follow Planet Mozilla to be up to date with the happenings in the community. Over time I became aware of the fact that, while some people hosted their pages or blogs on free services or their company/university domains and servers, others owned their domain names and servers used for the same purpose.

At that time (and for a while after that) I wasn’t aware of the value of owning a domain name, but I roughly understood the main argument for self-hosting your website, which is independence from a particular organization you might cease to be affiliated with. In addition, with social networks centralizing interactions on the web and creating walled gardens of content, having your own domain and setting up your own communication services (be it web, e-mail, or XMPP) is a good way to contribute to Internet remaining decentralized.

It still took me until late 2014 to bite the bullet and move from Department of Informatics‘s to my own domain ( at the moment) and my own hosting. At the time, I already had some experience with setting up and troubleshooting Apache. It was mostly coming from a few years of maintaining the Department’s inf2 server, where MoinMoin used to be the prime tenant, but a number of PHP applications also found their home.

Despite being lazy about registering my own domain and setting up my own web server, I must mention that I did keep my page reasonably up to date, i.e. at least once a year I would make sure that all the content (courses, scientific work, interests, software etc.) is still correct. (It’s not the only instance where I work hard not to repeat the mistakes of my professors observed while being their student.)

I mentioned my decision to Domagoj, suggested to him to do the same, and offered my help and support if he would decide to register his own domain and set up his own website. (I also wished my professors would have explained to me the value of the domain names and encouraged me to get one, so there is that trying to improve on what they did.) To my pleasant surprise, he was convinced by the arguments about decentralization and independence that I brought up at the time and also detailed above.

From that moment I knew that a day will come when a little bird will grow up and decide to leave the nest and create their own, i.e. Domagoj will want to set up his own hosting that he will have complete control of, and in the future use it to help others walk the same path. That’s precisely how things should be, that’s exactly how new Internet nodes should appear, and that’s exactly how Internet should grow towards becoming more decentralized.

Fly away, little bird, the world is awaiting you.

Why use reStructuredText and Sphinx static site generator for maintaining teaching materials

Featured image: Les Anderson | Unsplash (photo)

Yesterday I was asked by Edvin Močibob, a friend and a former student teaching assistant of mine, the following question:

You seem to be using Sphinx for your teaching materials, right? As far as I can see, it doesn’t have an online WYSIWYG editor. I would be interested in comparison of your solution with e.g. MediaWiki.

While the advantages and disadvantages of static site generators when compared to content management systems have been written about and discussed already, I will outline our reasons for the choice of Sphinx below. Many of the points have probably already been presented elsewhere.

Starting with MoinMoin

Teaching materials for the courses some of my colleagues and I used to teach at InfUniRi and RiTeh, including laboratory exercises for the Computer Networks 2 course developed during early 2012, were initially put online using MoinMoin. I personally liked MoinMoin because it used flat text files and required no database and also because it was Python-based and I happen to know Python better than PHP.

During the summer of 2014, the decision was made to replace MoinMoin with something better because version 1.9 was lacking features compared to MediaWiki and also evolving slowly. Most of the development effort was put in MoinMoin version 2.0, which, quite unfortunately, still isn’t released as of 2017. My colleagues and I especially cared about mobile device support (we wanted responsive design), as it was requested by students quite often and, by that time, every other relevant actor on the internet had it.

The search for alternatives begins

DokuWiki was a nice alternative and it offered responsive design, but I wasn’t particularly impressed by it and was also slightly worried it might go the way of MoinMoin (as of 2017, this does not seem to be the case). It also used a custom markup/syntax, while I would have much preferred something Markdown/reStructuredText-based.

We really wanted to go open with the teaching materials and release them under a Creative Commons license. Legally, that can be done with any wiki or similar software. Ideally, however, a user should not be tied to your running instance of the materials to contribute improvements and should not be required to invest a lot of effort to set up a personal instance where changes can be made.

MediaWiki was another option. Thanks to Wikipedia, MediaWiki’s markup is widely understood, and WYSIWYG editor was at the time being created.

In an unrelated sequence of events I have set up a MediaWiki instance in BioSFLab (where I also participated in research projects for almost two years) and can say that setting up such an instance presents a number of challenges:

When migrating a MediaWiki instance from a server to another server, you have to dump/restore the database and adjust the config files (if you’re lucky it won’t be required to convert Apache configuration directives to Nginx ones or vice versa). None of this is especially complicated, but it’s extra work compared to flat file wikis and static websites.

Finally, my favorite MediaWiki theme (skin in its terminology) is Vector, so my potential wiki with teaching materials would look exactly like Wikipedia. While nice and trendy, it is not very original to look like Wikipedia.

Going static, going reStructured

Therefore, we opted to use Sphinx and reStructuredText, as it was and still is a more powerful format than Markdown. We specifically cared about the built-in admonitions, which made it easier for us to convert the existing contents (Python socket module lecture is a decent example). The advantages of Sphinx were and still are the following:

There is a number of issues which affected us:

  • the time to deployment after the change: varies depending on the change, but it’s in the order of tens of seconds in the worst case,
  • the need to automate the deployment upon git push (note that this does not increase attack surface, since git uses SSH or HTTPS for authentication and transfer).
  • learning curve to add content: MediaWiki’s WYSIWYG editor beats using git and reStructuredText in terms of simplicity.


A rule of thumb here would be:

  • if many people inside of an organization are going to edit content a lot and the content is more like notes than a proper documentation, then MediaWiki (or DokuWiki) is the choice,
  • if the content has an obvious hierarchy of parts, chapters, sections etc. and/or it is evolving like a piece documentation changes with software it documents, then Sphinx (or any of Markdown-based generators, e.g. HotDoc or MkDocs) will do a better job.

Enabling HTTP/2, HTTPS, and going HTTPS-only on inf2

Featured image: John Moore | Unsplash (photo)

Inf2 is a web server at University of Rijeka Department of Informatics, hosting Sphinx-produced static HTML course materials (mirrored elsewhere), some big files, a WordPress instance, and an internal instance of Moodle.

HTTPS was enabled on inf2 for a long time, using a self-signed certificate. However, with Let’s Encrpyt coming into public beta, we decided to join the movement:

HTTPS was optional. Almost a year and a half later, we also enabled HTTP/2 for the users who access the site using HTTPS. This was very straightforward.

Mozilla has a long-term plan to deprecate non-secure HTTP. The likes of NCBI (and the rest of the US Federal Government), Wired, and StackOverflow have already moved to HTTPS-only. We decided to do the same.

Configuring nginx to redirect to https:// is very easy, but configuring particular web applications at the same time can be tricky. Let’s go through them one by one.

Sphinx-produced static content does not hardcode local URLs, and the resources loaded from CDNs in Sphinx Bootstrap Theme are already loaded via HTTPS. No changes were needed.

WordPress requires you to set the https:// URL in Admin, Settings/General. If you forget to do so before you go HTTPS only, you can still use the config file to adjust the URL.

Moodle requires you to set $CFG->wwwroot in the config file to https:// URL of your website.

And that’s it! Since there is a dedicated IP address used just for the domain, we can afford to not require SNI support from the clients (I’m sure that both of our Android 2.3 users are happy for it).

How to get Facebook Messages working in Firefox for Android without the Messenger app

Featured image: Loic Djim | Unsplash (photo)

When one tries to use Facebook Messages from a browser on a phone or tablet running a relatively recent Android, the website ( or will open the Google Play store. Some of us prefer using browsers and avoid installing apps when possible. Unfortunately for us, Messenger does not offer a mobile website, only a link to download the app.

Luckily for us, there a are a few tricks that will help get Facebook Messages working from a browser on Android.

Google Chrome

The trick to avoid Facebook’s nagging is to enable “Request Desktop Site” in Chrome Menu. The explanation of what this option does is available on Stack Overflow.

Mozilla Firefox

Firefox also has the “Request Desktop Site” but, unfortunately, it doesn’t do the job; you actually get the desktop version of Facebook and it’s quite unusable.

One option is to use Unfortunately, mbasic is neither as functional nor as pretty as m, let alone touch.

The way to get Messages working on m or touch is to pretend to be running a version of Android that is unsupported by the Messenger app. In my experiments, anything older than 4.4 will do the trick, so I picked 4.3.1. You can pick your poison from Wikipedia, but bear in mind that using very old versions might get Facebook mobile website to use workarounds which are no longer needed and will break stuff if used.

To pretend to be using an old version of Android, we will alter the Firefox’s user agent string. In Firefox, go to about:config. Add a new String option called general.useragent.override the and set it to e.g.

Mozilla/5.0 (Android 4.3.1; Mobile; rv:48.0) Gecko/48.0 Firefox/48.0

Compare this with the default usera gent string which is in my case

Mozilla/5.0 (Android 6.0.1; Mobile; rv:48.0) Gecko/48.0 Firefox/48.0

Note that this string will not be automatically updated when Firefox is updated, so you should take care to update it manually. For more information about the user agent override option, check out this Super User question.