Build a blog using the Pelican static site generator

  Last modified on Friday 30 December 2016

Pelican is a Python-powered static site generator. I design the look and layout of this site using CSS and Jinja2 templates and write my posts as plaintext files using reStructuredText and Pelican compiles the contents into HTML output suitable for a blog.

I like the idea of creating a static website. Some of the advantages:

The traditional disadvantage to using static pages for a blog has been the lack of dynamic elements - hosting feeds, user comments - but JavaScript for things like a Twitter widget to provide real-time updates and out-sourced services like Disqus for commenting are possible alternatives to work around static limitations.

This is how I built Circuidipity on Ubuntu 16.04 using Pelican.

0. Install

I install Pelican and extra tools by creating a virtual environment using virtualenv and pip. This allows me to create a sandboxed work area specific to my blog and user separate from my default Python installation (an alternative method in Debian would be to install the python-pelican package) ...

$ sudo apt install virtualenv
$ mkdir ~/code/virtualenvs
$ virtualenv ~/code/virtualenvs/pelican
$ source ~/code/virtualenvs/pelican/bin/activate
(pelican)$ pip install pelican

Upgrading: simply run pip install --upgrade pelican.

Next I create a directory to hold my blog contents and run pelican-quickstart to create a default site layout and configuration. I add my blog details and mostly accept the default choices provided (except for pagination) ...

(pelican)$ mkdir -p ~/code/circuidipity/www
(pelican)$ cd ~/code/circuidipity/www
(pelican)$ pelican-quickstart

... and this is the layout generated ...

$ tree
├── content
├── Makefile
├── output

2 directories, 5 files

1. First post

Posts go into content and I create an images subdirectory for screenshots and artwork and a pages subdirectory to hold things like an about or contact page ...

$ mkdir content/{images,pages}

Inside content create your first post hello_world.rst using reStructuredText ...

Hello World

:date: 2014-02-06 23:24
:slug: hello-world
:tags: pelican, web, python

My *first* post using `Pelican <>`_!

Items like :date :tags: :slug: are metadata that can be used in the generated HTML output. These and a few others are included in Pelican and users can create their own to use in templates.

Save the file and test the new blog by running the Pelican built-in development server. This will take all the *.rst files and generate HTML formatted files in output and serve up the results for inspection in a browser at http://localhost:8000 ...

(pelican)$ make devserver

Server will continue to run in the background and re-generate any updated content for viewing. Stop server by running ./ stop.

2. Settings

Running pelican-quickstart creates 2 configuration files: and

Primary settings are configured in Settings can be used as variables in posts, pages, and templates. This is how mine looks ... some of the settings such as AUTHOR and SITENAME were generated by Pelican and some like WHOAMI_URL were created by myself.

A few of the settings like RELATIVE_URLS = True and turning off ATOM feeds are appropriate for a test environment but are probably things that need to be modified when its time for deployment.

The second configuration - - contains priority settings for publishing content.

3. Plugins

Plugins are available to extend the functionality of Pelican. I use a plugin called neighbors that makes it easy for me to add links near the bottom to Newer and Older articles in relation to the current page. After enabling the plugin in I make use of the plugin's next_article and prev_article variables in a Jinja2-formatted template to add those navigation links ...

{% if article.prev_article %}
    <p class="prevpost"><i class="fa fa-arrow-left"></i> Older<br />
    <a href="{{ SITEURL }}/{{ article.prev_article.url}}">{{ article.prev_article.title }}</a></p>
{% endif %}
{% if article.next_article %}
    <p class="nextpost">Newer <i class="fa fa-arrow-right"></i><br />
    <a href="{{ SITEURL }}/{{ article.next_article.url}}">{{ article.next_article.title }}</a></p>
{% endif %}

4. Themes

Pelican includes a default theme to get you started and there is a collection of user-created themes to choose from or create your own. I chose to start from scratch and explore CSS, Jinja2 templating, pygments and Font Awesome icons to create my own custom theme.

5. Publish

When ready to generate for deployment run ...

(pelican)$ make publish

All blog contents are placed in output ready to be uploaded to a hosting service. Since everything is static content there are many options available. I use a free project repository hosted on GitHub Pages.

Happy hacking!

More • pelicanwebpython