Blogging with Pelican & Github Pages

Sat 23 June 2018


This post documents my (mis)adventures setting up a blog using Pelican - a static site generator, very much like the popular Jekyll & Go frameworks, except it is powered by Python, not Ruby or Go. I decided to make the switch despite years of stability with Jekyll, because Python.

Installing Pelican


I wanted to have the ability to add some customizations of my own, so I decided to install Pelican from source. I created 2 separate folders: dev to contain local experimentation and prod to publish finalized edits to my Github Pages repository. The local setup is only concerned with dev. Run the following command inside an (preferably empty) directory on your machine where you want to store your website contents.

git clone https://github.com/getpelican/pelican.git dev

As mentioned in the documentation, create a virtual environment first using virtualenv before proceeding with any further installation. I called mine website. Start it up like so -

virtualenv ~/envs/website
source ~/envs/website/bin/activate


Tip: It can get annoying to remember the path to the folder where you store your virtual environments and type source bin/activate to switch into one. To get around the following, add the following to ~/.bash_aliases -

function workon() {  
    source ~/envs/$1/bin/activate  
}

and you can now switch into a virtual environment by simply typing workon <env name> at the command line from anywhere in your filesystem.

Now navigate to the dev folder which contains the pelican source code pulled from Github in the first step and run the setup scripts.

cd dev
python setup.py install
pelican-quickstart


pelican-quickstart sets up a base installation by posing you a bunch of questions. This should create a some new folders under dev including output, which contains the final static HTML of the website. To view the output locally, my preferred way was to have 2 separate tmux sessions. One running the content regeneration on autoreload -

pelican content/ -r -s pelican/settings.py

and another, building the HTML and serving it up on localhost -

make html && cd output && python -m SimpleHTTPServer

For some reason, my experience with the make devserver command was not ideal. You can now view how your blog looks on localhost:8000 and preview changes before publishing it live on your website.

Tip: The pelican-themes tool makes it super-easy to install and switch between themes. This blog uses the skyfall theme (with a few additions of my own), because it is the closest I found to some clean Hugo themes I'm fond of. To install a theme like skyfall, simply run the following under the dev folder -

git clone https://github.com/avinassh/skyfall.git pelican/themes/skyfall
pelican-themes -i pelican/themes/skyfall

and add a rule to pelicanconf.py -

THEMES = u'pelican/themes/skyfall'

Upon rebuilding, the site will reflect the change and you can continue working further.

Adding Emoji Support


Sadly, Pelican doesn't support have in-built support for emoji like Jekyll does. Not like I really care about emoji, but I really wanted to add in a grinning_face emoji at the end of my first blog post. Don't judge. I didn't find anything under the Pelican Plugins, but, serendipitously, one of my programmer heroes, bytefish, had published a solution to this just 2 weeks ago. His post detailing it is pretty self-explanatory, however, I'll fill in some blanks, if you make the same missteps I did.

To get started, fetch the source code for the extension and install it on your machine. If you care a lot about separation of concerns, make sure you switch over to the website virtual environment, before executing the following commands in a folder where you want to store software -

git clone https://github.com/bytefish/MarkdownEmojiExtension
cd MarkdownEmojiExtension && python setup.py install

This will install the emoji extension within the website virtual environment. However, before we are able to use it further, note some quirks of it -

  • To parse emoji in your posts correctly, you need to wrap them in 2 colon groups when you're writing, and not 1 like you may be used to viz. 😀 instead of :grinning_face:

  • The extension assumes that you have the mapping between emoji identifiers and their corresponding unicode stored as a list in a file called emojis.json under a resources folder at the root of your perlican installation - which, in our case, corresponds to the dev folder. So your dev folder would look like -

dev  
|  
+-- pelican/  
|  
+-- requirements/  
|  
...  
...  
|  
+-- resources/  
   |  
   +-- emojis.json


Emoji Dictionary


As mentioned in the original blog post for the emoji extension, a good reference for emojis can be found here - https://github.com/shanraisshan/EmojiCodeSheet. The data we need to get is under the json/string folder. I wasn't about to download an entire repo of data I'd most likely never use. So instead, I used the handy GitZip extension to download that specific folder as a zip file. Extracting the contents of the zip folder will keep all the files under json/string in the directory where you downloaded it. An interesting fact about the structure of these files - all the key-value pairs are under 2 layers of nesting. For eg.

Nature.json

{  
    "natures":  
        "nature": [  
            {  
                "key": ... ,  
                "value": ...  
            }  
            .  
            .  
            .  
        ]  
}

People.json

{    
    "peoples":
        "people": [
            {
                "key": ... ,
                "value": ...
            }
            .
            .
            .
        ]

}

Thus, accessing the key-value pairs can follow a common structure for all files. This common structure makes it straightforward for us to compose them all into one file.

Rolling a single emojis.json


Due to my deficient knowledge of Unicode, I couldn't get the formatting right using various Python functions. Finally, after an hour of trying, I lost my patience and turned to Rube Goldberg-ing it with sed. This hack will get all the key-value pairs inside one single file called emojis.json -

for filename in /home/varad/json/string/*.json; do  # loop through all the json files containing emojis
    sed -i ':a /\[/!{N;ba}; s/.*\[//g' $filename;   # join all lines until the '[' character
    sed -i 's/\]/,/g' $filename;                    # replace the ']' character and with a ',' to enable extension of the list
    head -n -2 $filename >> emojis.json;            # remove the last 2 lines of the file to enable extension of the list
done

sed -i '1s/^/\[ /' emojis.json                      # Add a '[' to the top of the file to denote the start of a list
sed -i '$ d' emojis.json                            # Remove the last ','
sed -i -e "\$a]" emojis.json                        # Add a ']' to the end of the file to denote the end of a list

The file emojis.json now has an extensive list of emoji that we can use.

Completing the setup


We now have everything we need to start working with bytefish's emoji extension. Go back to dev, and into the pelican folder therein to make the required edits to settings.py. Here's where a misstep might occur - depending on how you configured it, the path to the emoji extension .egg file might not be part of your PYTHONPATH. To ensure that happens, add the following to settings.py, before the import statement for the emoji extension.

import sys
sys.path.append("/home/varad/envs/website/lib/python2.7/site-packages/emojiextension-1.1-py2.7.egg")

Of course, you should replace that path with wherever your extension got installed (you would have gotten that location's path after the setup script completed). If you've been following along this post, you only need to replace varad with your username.

Another possible misstep is not having emojis.json in the right location. So, inside dev/pelican, make a folder called resources and copy the previously generated emojis.json to this folder.

Once done, simply run python setup.py install from the dev folder again to re-build Pelican and you will now have emoji support!

Publishing with Github Pages


This is by far the most trivial step in the entire process. Since the live blog is only concerned with the final HTML output, I copy the contents of the output folder into the as yet unused prod folder we created in the beginning and simply push that to the master branch of my Github Pages (varadgunjal.github.io) repository. And that's it! The changes should be live almost immediately thereafter!   🤘

Questions? Corrections? Let me know in the comments section below.