This is the fourth article in a series about setting up my own website using a Static Site Generator. For other articles in the series, click on the title of the article under the heading “Static Site Generators” on the right side of the webpage.


In the previous articles, I was able to verify my setup of Pelican, posting a test article that I was able to view in a browser. I was then able to improve the fidelity of that article by using Lorem Ipsum to make sure it looked more like a real article in terms of content and length. Almost as important, I was able to come up with a more efficient workflow for publishing changes as I work on them.

To make the jump from authoring to publishing, there are a number of things that I needed to finish:

  • Fixing The Build Warning
  • File Types and File Paths
  • Better Values For Defaults
  • A Default About Page
  • Selecting a Theme

Once all of that was completed, I should be ready to publish… so let’s proceed!

Before We Start

Please read Operating System Paths from the second article in this series for my view on operating system pathing. (i.e. /mount/my/path vs. c:\my\path). To understand the term base project directory and the script text %%%MY_DIRECTORY%%%, please read the explanation under Step 2: Create a Project Directory For The Site, also from the second article in this series.

Task 1: Fixing The Build Warning

When the site was regenerated using the pelican-build.bat file, I noticed a warning at the top of the output.

WARNING: Docutils has no localization for 'english'. Using 'en' instead.

This is an easy one to handle. I went to the and changed the value for DEFAULT_LANG from english to en. Running pelican-build.bat again, the warning went away. This was simply changing the value from a human readable format to the ISO 2 letter code for the language, so it was an easy fix all around.

Task 2: File Types and File Paths

Even though I am creating a static website, there are various categories of content that I feel should be kept separate, for various reasons. Luckily, the contributors to Pelican though of this too, and the following change to separated the different forms of content:

ARTICLE_PATHS = ['articles']
PAGE_PATHS = ['pages']
STATIC_PATHS = ['images']

This configuration informs Pelican that articles will be contained within the content\articles directory, pages within the content\pages directory, and static content, such as images, in the content\images directory. While this isn’t 100% necessary at the moment, I feel that the organization will pay off later in the website’s history.

To complete this change, I moved the content\ file into the content\articles\ directory to follow this paradigm. To make the paradigm more complete, I wanted to make sure that the articles that I write have the date they were created as part of their published path. Searching around the Pelican site itself, this was easily accomplished with the following change:

ARTICLE_URL = '{date:%Y}/{date:%m}/{date:%d}/{slug}/'
ARTICLE_SAVE_AS = '{date:%Y}/{date:%m}/{date:%d}/{slug}/index.html'

Task 3: Better Values For Defaults

The file contains two variables, LINKS and SOCIAL, which are still at their default values. Giving each a better value will give me a better idea of what things will look like with various themes, so it makes sense to change them now to:

            ('Pelican', ''),
            ('github', ''),

Task 4: A Default About Page

In trying to determine what I needed before looking at themes, I noticed one small gap: I had no static pages. While I expect most of my content to by blog posts, there will be the occasional times where I want some kind of page on my site that isn’t an article.

The first type of page that came to mind was an About page, so I quickly created a new file content\pages\ with the contents:

# About Me

This is me.

While it is just a placeholder, the intent was that it would give me a good idea of what to expect going forward.

first article view

In Pelican, extensions are performed using a combination of configuration, pip installs, and git repositories. The configuration changes and pip installs felt natural to me, as they are common paradigms in Python. However, I found the repositories as source took a bit of getting used to. Not too bad, but a bit of change that was good!

Themes themselves are each an individual git repository, containing all of the asserts that the theme needs. Luckily there is a site that shows samples of approximately 80% of the themes. While it is a bit to process in one viewing, Pelican Themes currently contains 126 themes, of which 100 of them have images of themed pages. The better themes have 3-4 pages shown in the index, whereas some of the themes only have 1 image. Regardless, it is a lot better than downloading 100 themes and trying each one out!

Task 5: Selecting a Theme

At this point, I was pretty sure I had all of the assets I needed before I looked at themes. Sample articles. Check. Sample page. Check. Sample Links. Check. Sample social links. Check. It was time to start!

Seeing as I hadn’t actually read anything in people’s blog posts about how hard it was to select a theme, I wasn’t sure what to expect. As such, I budgeted a decent amount of time to the effort. In fact, I actually budgeted a whole week for this next section. For me, the choice of theme was pivotal in being able to communicate effectively with readers.

To be clear, I didn’t need it to be the right choice. I did need it to be the right choice for me and my voice. It was a clear proposition in my mind: come out of the gate with a theme that wasn’t me, or take the time and try and nail it. Even if I missed by a bit, I wouldn’t regret taking that time.

If you are following these articles as a guide, remember that. Give yourself the time to make a solid choice that you believe in.

Which Themes to Try?

As I was trying to find a theme for myself, I went through the complete list of themes 3 or 4 times, just taking a look and seeing which ones appealed to me and which ones had ideas that I liked. I started a list on the first pass, and with each pass through the list, I whittled that list down based on what I saw.

On the final pass, I focused on getting the number of themes down to a manageable 3 themes. For that pass, I found it important, yet difficult, to pare down the choices to 3 themes. It was important, because I didn’t want to be stuck analyzing the themes for a long time. It was difficult because there are a lot of good options for themes, and to come up with only 3 options wasn’t easy. However, I found that by focusing on my primary goal of ease of use from my first article, both ease of writing and ease of reading, it helped me narrow things down.

The use of an actual list, in my case a simple list written in Markdown, was pivotal. At first it contained the URLs of each of the repositories I wanted to look at more. With each pass through the list, it contained more information about individual themes and a smaller number of themes, This approach helped to quickly whittle the selection down to the real contenders. This approach, while pedantic, saved me a number of times, as it became more of a struggle to remember which theme had which look and which features.

With my final pass through the list, I arrived at my top pick of the nice-blog theme, with alternates of the blueprint theme and the elegant theme. Nice-blog is simple and uncomplicated, with a decent looking sidebar. blueprint is the theme for the site of Duncan Lock which I found during my research. blueprint had a bit more of a finished techy feel, with a nice layout on the sidebar. Each article had “X min read” text with the clock icon really grabbed me, which really appealed to me. Finally, the elegant theme seemed to keep things simple but elegant, with lots of room for creativity.

Trying Out The Themes

Each of the themes, Nice-Blog, Blueprint, and Elegant, exists in it’s own GitHub repository. As such, one approach to downloading the themes was to create a blog-themes directory at the same level as the base project directory, creating a directory for each theme. As Nice-Blog and Elegant are in the main Pelican themes repository, the other approach for those two themes was to clone the Pelican Themes Repository into the blog-themes directory using:

git clone --recursive

For the first approach, I would have to individually add each theme, whereas with the second approach, I can get most of the themes all at once. The was also the concern that regardless of which way I chose for nice-blog and elegant, I would have to use the first approach for blueprint. Was it worth it to have two paradigms?

After thinking about it a bit, I decided to go with the first approach, as I only had 3 themes I was interested in. So, on the command line, I entered:

mkdir ..\blog-themes
git clone ..\blog-themes\nice-blog
git clone ..\blog-themes\blueprint
git clone ..\blog-themes\elegant

The plan was to try each of the candidates, writing down notes about what aspects I found good and bad about each. Following the instructions on the Pelican home page, I modified to refer to the first theme as follows:

THEME = '%%%MY_DIRECTORY%%%\\blog-themes\\nice-blog'

Save the file, switch to the browser and refresh. Check to make sure it changed properly. Look around the site a bit and write down some notes. Easy. While I would end up coming back to this theme later for more information, the first pass was a solid 5 minutes with no issues.

Expecting similar behavior, I did the similar change to make the THEME variable point to the blueprint directory. I switched to the browser and refreshed and it was the same as before. A quick examination of the Builder command window, and I got the following notification:

CRITICAL: TemplateSyntaxError: Encountered unknown tag 'assets'.

Critical error… encountering that was foreboding. I stopped the windows started by pelican-devserver.bat, and buckled down to do more research. This was the start of a long diversion.

Off The Beaten Path: Getting Blueprint to Work

Note: I have not contacted the developer of the Blueprint theme, and his blog and his theme have not had any recent changes. When I decided to try it out, it was with the knowledge that it would probably require more effort to get it to work.

I had hoped to wait for a bit before exploring plugins, as there are many plugins listed on the Pelican Plugins website. In addition, unless you know what you are looking for with a plugin, it’s effects are either invisible or difficult to spot. For those reasons, I wanted to wait until the more major variables regarding the website were set before tackling these more minor ones.

Adding Required Plugins

After doing my research, it appeared that blueprint was dependent upon the assets plugin. While installing Plugins faces the same issue as how to install Themes, I chose to do the “all at once” approach for the plugins. The main reason for this was to allow me in the future to try each plugin, figuring out that plugins is worth the impact. As such, having all of the common plugins together made a lot more sense.

Similar to the way described above to install all the themes, I created a blog-plugins directory at the same level as the base project directory. Changing into that directory, I issued the following command to pull the contents down to my system.

git clone --recursive ..\blog-plugins

Once I had the contents of the plugin repository on my machine, I added configuration to Pelican to point to the new plugin directory. Then I needed to add the assets plugin to satisfy the blueprint theme. This was done by adding the following to

PLUGIN_PATHS = ['../../blog-plugins/']
PLUGINS = ['assets']

Running the pelican-build.bat script this time, I received the following error, buried deep within the output:

WARNING: `assets` failed to load dependency `webassets`.`assets` plugin not loaded.

Plugins With Python Package Requirements

Luckily, as part of the previous research, this warning was mentioned, and it was because the assets plugin requires the webassets Python package. A quick pip install webassets later, it’s time to build the website again.

This time, after running the build script, the output ended with the following lines:

CRITICAL: ValueError: not enough values to unpack (expected 3, got 2)
  File "XXX\blog-themes\blueprint\templates\base.html", line 37, in top-level template code
    {% for anchor_text, name, link in SOCIAL %}
ValueError: not enough values to unpack (expected 3, got 2)

Configuration Changes For Plugins

Once again, research to the rescue, this being a relatively easy issue. Different plugins and themes have different configuration requirements, and this one is no different. By looking at the error message, mixed with my knowledge of Python, I saw that the plugin is expecting 3 values for the SOCIAL configuration variable: anchor_text, name, and link. A quick look at my current configuration, and I see the default settings of:

            ('github', ''),

represent the 2 values that the theme is expecting. Needing a third, I simply cloned the first value into the second position:

          ('github', 'github', ''),

Wash. Rinse. Repeat. Running the script again, I received the following critical error:

CRITICAL: TemplateAssertionError: no filter named 'sidebar_date_format'
  File "XXX\blog-content\virtualenv\lib\site-packages\jinja2\", line 315, in fail
    raise TemplateAssertionError(msg, lineno,, self.filename)
jinja2.exceptions.TemplateAssertionError: no filter named 'sidebar_date_format'

More Configuration Changes

This time, it took a lot of looking. I did scans over the entire blog-themes directory as well as the blog-plugins and blog-content directories. Just in case. In fact, I had almost given up hope when I started to look at the file that Duncan himself used. Down near the bottom were a number of configuration entries, including one for the missing configuration item.

from datetime import date
def month_name(month_number):
    import calendar
    return calendar.month_name[month_number]

def custom_strftime(format, t):
    return t.strftime(format).replace('{S}', str( + suffix(

def archive_date_format(date):
    return custom_strftime('{S} %B, %Y', date)

def sidebar_date_format(date):
    return custom_strftime('%a {S} %B, %Y', date)

def suffix(d, wrap=True):
    tmp = 'th' if 11 <= d <= 13 else {1: 'st', 2: 'nd', 3: 'rd'}.get(d % 10, 'th')
    if wrap:
        return '<span class="day_suffix">' + tmp + '</span>'
        return tmp

# Which custom Jinja filters to enable
    "month_name": month_name,
    "archive_date_format": archive_date_format,
    "sidebar_date_format": sidebar_date_format,

Copying this into my own file, it was time to run the build script again. To be honest, for this section of configuration, I started only copying the sidebar_date_format function. Then I realized it needed custom_strftime. Then I realized it needed… It was at that time that I figured it was easier to just copy all of this code over, and if I stayed with the theme, I would see about cleaning it up.

With the complete section copied over, running the build script produced the following error:

CRITICAL: UndefinedError: 'pelican.contents.Article object' has no attribute 'stats'

More Build Iterations

Realizing that more of the configuration may be in the file, with the above error in mind, I scanned the configuration and noticed a plugin called post_stats. Looking at the documentation for post_stats, it seemed like it would expose that attribute. So, adding ‘post_stats’ to the plugins, I re-ran the build, with the attribute error disappearing, only to be replaced with:

ModuleNotFoundError: No module named 'bs4'

Having looked at the documentation for post_stats, I was able to solve this one right away. To get the proper word count for the stats, the plugin uses the Python Beautiful Soup package (version 4) to scrape the HTML output. Executing pip install beautifulsoup4, and then rebuilding again, we get the following output:

File "%%%MY_DIRECTORY%%%\blog-themes\blueprint\templates\footer.html", line 41, in top-level template code
    {% for anchor_text, name, link in LINKS %}
ValueError: not enough values to unpack (expected 3, got 2)

This is the same error as with the SOCIAL variable, and the same solution will work. Changing the LINKS variable to:

            ('Pelican', 'Pelican', ''),

And recompile and… all errors gone. Switch back to the browser and refresh the page. Repeat the entire process as with the nice-blog theme, taking notes.

Back to the Final Theme

Bracing for the worst, I changed the theme to Elegant and it… just worked. After blueprint, I expected a lot more effort, but it just worked. Counting my blessings, I did the usual playing around and taking notes, then I sat back.

From then on, I went back to the three themes frequently and took more detailed notes and observations until I got to a point where I wasn’t adding any meaningful notes. It was then that I was sure that I had the information I needed to make my decision.

Lessons Learned

Before I go on to my decision process, I wanted to go over some things I learned or remembered along the way of finding a theme. Some are obvious, some are not.

  1. The more standard things are, the less you are going to have to do to make them work.
    • Blueprint was not in the main collection of themes, and it took a lot of effort to make it work in it’s out-of-the-box mode.
    • Elegant and Nice-Blog both worked out-of-the-box with 0-2 modifications to configuration and no extra packages or plugins.
  2. The auto-build feature of the generator can hang.
    • There were a number of times I had to Ctrl-C and restart the generator.
    • This seemed to happen more when I was changing the themes or plugins.
    • It also happened when I introduced something that required a new Python package.
  3. I didn’t regret putting in the work.
    • I wanted to put the work in to each theme on the short list to have a balanced comparison.
    • I wanted to have a good understanding of what it would take to maintain each of the themes. The work I put in gave me the understanding that blueprint would take a lot more work than the others to maintain.
  4. As old school as it is, a simple pros and cons list help me figure out the best theme.
    • The first two themes were easy to keep in my head at first.
    • The more themes that I saw, the harder it was to remember any points about each of the themes.
    • By the time I got down to the last 2 themes, I had so many parts of so many themes going through my head. Without the list, I would have been lost.

The Final Selection

Due to the amount of work required for blueprint, including a number of limitations I encountered clicking around, it was out of consideration right away. One of my core issues from the first article was ease of use, and I didn’t get the feeling that blueprint would fall into that category.

Looking at the notes a number of times, it was hard to distinguish the two remaining themes from each other. They both had a simple and elegant look-and-feel, and that was making the decision even more difficult. There were a couple of small features that were different, but those missing from one were balanced by ones missing from the other one. It was pretty much a stalemate in my head.

After going back and forth a number of times to try and resolve the stalemate, I decided I needed more criteria to help. The first two that came to mind were the documentation and active maintenance of the theme. This was returning to the ease-of-use consideration that was a driving force in my first article, so I knew it would be relevant. It was then that the elegant theme became the winner by a fair amount.

So, after about a weeks worth of shifting between themes in “spare time”, I landed on the elegant theme for my website. It took a couple of days for it to sink in while I was writing this article, but with each passing day, my confidence that I made the right choice increased. I took the time, examined the themes, wrote the notes, and in the end, it resulted in a single, clear choice.

With finality I went to the configuration file, and near the top added:

# Current Theme
THEME = '%%%MY_DIRECTORY%%%\\blog-other-themes\\elegant'

What Was Accomplished

At the beginning of this article, I had most of what I needed to start selecting a theme. It took some small updates to the configuration to make sure I had a good test site available. This was critical to allowing me to go through each theme I was interested in and see if it was for what I was looking for. While one of the themes proved to be a handful, the experience was good in advising me of possible issues I might have in customizing my own site.

In the end, I made a strong, confident choice of the elegant theme, which as benefits, is actively being developed and has great documentation.

What’s Next?

Now that I have completed all of the major tasks, the next step is to publish the website to an external host. For choices that will become evident, I will be publishing the website to GitHub pages. Completing this task will be covered in the next post Publishing To GitHub Pages.

Epilogue: Jack’s Notes on Themes

In the previous sections, I mentioned taking notes on each themes. To do this, I used the main page, the about page, and the two sample articles as a litmus test. I clicked around the website, looking for things that worked and didn’t work, as well as the feel of the website. I also went to the home repository of each theme and checked for how often it was updated, and what kind of support the repository offered for customization.

In the end, I came up with three lists of items, with pros and cons, as follows:

  • nice-blog
    • pros
      • starting point
      • minimal but elegant look and feel
      • categories support
      • metadata for articles
        • subtitle, cover image, gallery
      • can change color easily
    • cons
      • doesn’t seem to handle TOC properly
      • no tags support
      • simple tracking
  • blueprint
    • pros
      • tags by name and frequency
      • like “4 min read”
      • nice blue
      • date format Fri 3rd December, 2010
      • category and tag support
      • origin of better figures plugin
    • cons
      • too limited otherwise
      • no archives by default
      • documentation for theme very limited
  • elegant
    • pros
      • nice layout
      • very elegant and simple feel
      • category and tag support
      • extensive documentation
      • lots of metadata
      • actively being maintained
    • cons
      • no “4 min read” support
      • no links support

Like this post? Share on: TwitterFacebookEmail


So what do you think? Did I miss something? Is any part unclear? Leave your comments below.

Reading Time

~16 min read


Static Site Generators


Integrating Technology


Stay in Touch