I've been using pelican as my static blog generator since I started this blog about one year ago. It only took a bit of configuration to get the blog up and running, and a bit of searching through pelicanthemes to find nikhil-theme which is the theme I'm still using.
While the base blog setup was easily done, it wasn't perfectly suited for my needs. This is when I started customizing a few things to make it fit my use. Thankfully pelican is really customizable, even offering a plugin interface in addition to the normal configurations. It is also written in python, so if all fails, I can always hack a patch together to get the job done 😝.
So as promised in the previous post, in this one I will talk about the main customizations I did to my blog so far. Throughout the text I'll link to the commits where I did the changes mentioned here.
The most impactful customizations I did were probably the pelican plugins I added. These aren't my own modifications, but given their importance I want to describe them.
i18n_subsites is great for my dual-language blog. By default, pelican supports only translating blog posts as standalone texts so that each translated post has links the translations. But what I really wanted was to have two versions of my blog, one in english and another in portuguese. Each with all the interface in its own language as well as only showing the posts of that language. This plugin enables exactly that.
It is a bit confusing to understand how to correctly configure it at first, mainly the template localization part, but hey, I learned about Jinja2 and gettext! Relevant commits: 1 (it was part of the initial commit, sorry), 2, 3, 4 and 5.
series I added a bit later. It's very simple but useful. In fact you can see it in action in this same post at the top. It's what enables me to make this post part of a series of posts and link to the other ones. Relevant commits: 1.
Separate RSS feed for each i18n sub-site
Also on the subject of translation, since I wanted separate sub-sites for each language, it also made sense to have a separate RSS feed for each of them. In the end this turned out to be a single line change, even though it took me a while to figure out how to do it. Relevant commits: 1.
Automatic language detection from filename
Another customization related to translations (it was a big thing for my blog! 😝) was setting the language of the post automatically from the file name. Since I already want the file for each translation of a post have the language in its name, this saves me from needing to input the language header as well.
For example, the files for this post are called
the english version, and
07-blog-custom-br.rst for the portuguese version.
Normally I'd also need to set a
lang metadata header for each one with the
corresponding language, but with this change it is set automatically 🙂.
Relevant commits: 1 (again, part of the initial commit 😅) and 2.
Icon setting for pages
When I was setting up the navbar on the top, I wanted to add an icon to each entry, to make it very clear what each one does. But the About page, unlike the others, is a page generated from rst and automatically added to the bar, so I couldn't set its icon in the HTML directly.
To solve this I created a custom
icon metadata header that holds the
FontAwesome icon name for the icon that will be displayed for the page on the
bar. Then I just added the name of that "info circle" icon for the About page
and now it looks much better 🙂. Relevant commits: 1.
Fix for literal rendering in rst
Let's wrap the post with the biggest change 😝.
First of all, some context: When I started the blog, I wrote the posts in Markdown. But a few months later I learned about reStructuredText (from here on, referred to as rst) because it was used in the Linux Kernel documentation, and started using it even more when I discovered rst2pdf, which I won't go into detail since I still plan on writing about it eventually. The point is that I started writing my blog posts in rst instead since it was supported by pelican.
But one really annoying issue I faced is that the default HTML generator for rst
translates literal blocks into
<tt> tags. This tag is deprecated in HTML5,
and the whole world uses
<code> for inline code, including my theme, which
meant literals didn't render right. (There are reasons rst doesn't use
<code> for literals, but for my blog they aren't relevant)
I could have just adapted my theme to workaround it, but that would be hiding
the problem: The deprecated
<tt> tag would still be there for the world to
At first, I worked around this issue by using the code role explicitly:
The following is a rst literal, so it will be inside a <tt> tag: ``blah`` The following uses the code role, so it will be inside a <code> tag: :code:`blah`
That is obviously a too cumbersome syntax for a blog that frequently uses inline
code, so I got tired of it quickly. I then started overriding the default role
code, and using single ticks instead of the double ticks syntax for
.. default-role:: code Now the following will use the code role: `blah`
Since the text is inside single ticks but doesn't have a role specified, it uses
the default one. Way better, but I still needed to write that
definition at the beginning of each document...
Finally, I thought of an even better solution: Create an rst reader plugin
for pelican which overrides the default reader only when parsing literals,
in order to output
<code> instead of
This honestly was easier than I expected. It just took a bit of copying from
pelican's and Sphinx's readers and worked perfectly! Now I could finally write
plain rst literals and have them be converted to
<code> tags without any
additional work 🙂. Relevant commits: 1 and 2 (this is just me updating all
blog texts to use the new syntax).
With these customizations, I have a blog I'm very comfortable with, both when writing and reading it. These changes I showed were the ones I thought were the most interesting, but naturally the whole code is open, so feel free to check the rest of it.