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 thedev
folder -git clone https://github.com/avinassh/skyfall.git pelican/themes/skyfall pelican-themes -i pelican/themes/skyfalland 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:
- This shouldn't be too much of a problem unless you communicate exclusively in emoji. And if you do, just change the regex inside
emojiextension.py
.
- This shouldn't be too much of a problem unless you communicate exclusively in emoji. And if you do, just change the regex inside
-
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 aresources
folder at the root of your perlican installation - which, in our case, corresponds to thedev
folder. So yourdev
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.