Perl programmer for hire: download my resume (PDF).
John Bokma's Hacking & Hiking

Create a static tumblelog with Python

April 7, 2019

Friday and Saturday I worked on porting my Perl version of a static tumblelog generator to Python. Even though I hadn't programmed in this language for quite some time I was able to write Python fluently again after a very short time.

One advantage of doing this, besides getting fluent in Python once more, was that I was able to refactor the Perl version here and there. Moreover, I found two bugs in the Perl version while porting. One was minor: the use of a global variable instead of the one passed as an argument to the function call, which didn't change the execution of the program. The second one could have caused unexpected output: I matched dates in the markdown input with the multiline flag, which would match a date in the right format in a blog entry as well. Both bugs have been fixed in the latest version available on GitHub.

Great care has been taken to make the generated blog of both the Perl and Python version identical. This meant I had to make a few small modifications to the Perl version. The only difference between the two programs is in the output of the errors and --help.

A screenshot of my tumblelog Plurrrr
A screenshot of my tumblelog Plurrrr.

I have my own tumblelog named Plurrrr which is generated using either the Perl version, which has the exact same output as the Python version, in case you want to look before you leap.

The following steps assume you run Ubuntu 18.10 or related.


The easiest way to download is to use git clone. You might have to install git first as follows:

sudo apt install -y git

Next, clone the repository as follows:

git clone

Change into the just created tumblelog directory:

cd tumblelog

Make sure to check for updates regularly using git pull.

Installing the required packages

The tumblelog generator requires the commonmark Python library to be installed. I used pip3 to install this library as follows:

sudo apt install -y python3-pip
pip3 install commonmark

After this, should be able to run without any errors. Verify this by running the program with the --help option:

python3 --help

Please take some time to read the help shown.

In order to create the CSS stylesheets the sass program has to be installed as follows:

sudo apt install -y sass

I use Sass, a CSS extension language, to make it easy to create new styles and maintain the current ones. I highly recommend to use Sass or a similar program in your own projects if you work with CSS.

A first test run

For a first test run we need first to create a directory for the CSS stylesheet and HTML files:

mkdir htdocs

Next, compile a stylesheet. At the time of writing Plurrrr, my own tumblelog, uses soothe.css. If you want to give this a try, run the following command:

sass --sourcemap=none -t compressed styles/soothe.scss htdocs/soothe.css

If you prefer a simpler, lighter theme replace soothe with black-and-white (twice) in the above line. Don't forget to keep the file extensions the same.

After you have created one or more stylesheets inside the htdocs directory you can run the Python program, for example, as follows:

python3 -o htdocs -t tumblelog.html -c soothe.css \
    -a 'Your Name' -b -n 'Test Blog'

If all went well you should now have an example blog with a few small entries in your htdocs directory. You can open the index.html in your browser and verify that the entries are there. One way to do this from the command line in Ubuntu is to run:

xdg-open htdocs/index.html


If all works well I recommend to customize the HTML template first. It's probably the best to copy the default template, tumblelog.html to a new file.

The template uses the following variables:

Variables have to be placed between [% %] and are expanded by the Python program to their values. All variables, except for body can occur more than once in a single template.

If you want to create your own stylesheet I recommend to use Sass and start with copying soothe.scss. Next, edit the colors in the copy you just made until you're satisfied with the result. If you want to share your stylesheet do a git pull request.

Writing your first blog post

Use tumblelog.html as a guide for how to write your own blog posts. I recommend to leave this file alone and create a new file for your own blog.

A day starts with a date in year-month-date format, for example 2019-03-30. A day can have one or more entries. Separate each entry with %. Optionally, give each entry a heading. Use ##, a level two heading and not a level one heading because otherwise validating the HTML of your blog gives the following warning:

Warning: Consider using the h1 element as a top-level heading only (all h1 elements are treated as top-level headings by many screen readers and other tools).

I recommend to validate the HTML after each change you made to the template.

In each entry you can use Markdown to mark up your blog entry.

Each day will generate a stand-alone HTML page. All entries of a week are collected in week overviews. The main page contains the entries of the last days the number of which can be specified on the command line, see --help.

Uploading to your site

To upload to my website I use the rsync program as follows:

rsync -avh --delete -c htdocs/ ti:sites/

With ti an entry in the SSH config file, located in ~/.ssh.

Host ti
     Port XXXXX
     User toxicice
     IdentityFile ~/.ssh/id_rsa

Note that I have masked the port number for security reasons.

This set up uses public-key authentication with SSH.

Furthermore, because I update my tumblelog very often I decided to create a small makefile similar to the one given below:

TUMBLELOG = ../../projects/tumblelog
PYTHON = python3
SCSS = soothe.scss
SASS = sass --sourcemap=none -t compressed
CSS  = soothe.css
TEMPLATE = plurrrr.html
AUTHOR = 'John Bokma'
NAME = 'Plurrrr'

all: local
	rsync -avh --delete -c htdocs/ ti:sites/

	$(SASS) $(TUMBLELOG)/styles/$(SCSS) htdocs/$(CSS)
	$(PYTHON) $(TUMBLELOG)/ --output-dir htdocs \
	  --template $(TEMPLATE) --css $(CSS) \
	  --author $(AUTHOR) --blog-url $(BLOG_URL) \
	  --name $(NAME)

Important: use tabs to indent the lines, not spaces in your makefile.

In this example I have my website in a different path than the tumblelog project. In your case you might have to change the TUMBLELOG variable besides the line containing the rsync command.

Note that I use --delete with rsync because I want an exact copy of the local directory on the server. If you have already a site on the server and want to keep those files make sure to remove the --delete option.

With this makefile you can create your local version using:

make local

And make the local version and upload it to your website using just


For more information, see a simple makefile tutorial.


I have taken great care to make the generated tumblelog pages valid HTML, SEO friendly, and Google friendly. With the exception that there is no sensible title because a day can contain multiple blog entries. This could be solved by specifying a title in the Markdown file but this would make things a little more complicated. Moreover, one has to come up with a title that somehow covers several entries. At least that's my case.

The generated pages for the current template and style sheets pass Google's Mobile-Friendly Test.