The Pelican quickstart site that we created in Part 1 used the default theme - which you will probably want to change or, at least, customize. In this post I break down the Pelican theme I created for this site and show you exactly how it’s built. I’ll be going through each part of the theme in depth, explaining why I did things that way and how each part works.
The theme for this site is professional grade - high quality, polished and responsive. It puts the focus on the reader, is 100% easy to read and works flawlessly at any screen size, including mobiles & tablets. It also takes into account best practices for both social media and Problematic, check error messages! : :abbr:`SEO (Search Engine Optimization)`, so that you can make the most of your writing.
Unknown interpreted text role “abbr”.
Before We Begin, a Word About Editing Workflow
I’m going to assume that you’re carrying on from Part 1 - so we’re using a python virtualenv
& virtualenvwrapper
, for example. With that in mind, here’s the workflow I’d recommend for working on your site. Open a text editor {fn-subl}, open a browser and point it at your local site, then open a Terminal window and run the following:
workon duncanlock.net-pelican
pelican -qrs pelicanconf.py
This should just sit there and monitor the site for changes and automatically rebuild it whenever anything changes:
--- AutoReload Mode: Monitoring `content`, `theme` and `settings` for changes. ---
-> Modified: content, theme, settings. re-generating...
Done: Processed 13 articles and 1 pages in 5.83 seconds.
To test it, open pelicanconf.py
in your text editor and just save it - this should trigger an automatic rebuild. Now, whenever you change anything - the theme, the content or the settings, that process will automatically notice & rebuild the site - you just save your changes, then refresh your browser window once it’s finished building.
Standing on the Shoulders of Giants
My theme - which I’m currently calling Blueprint - wasn’t created from scratch. It was based on an existing theme, from the pelican-themes repository. To checkout this repository and see what themes are available, just check it out from github with git
. Don’t do this in the same folder as your main site, do it somewhere else. This command will clone the repository into a folder called pelican-themes
, in the folder where you run it:
git clone --recursive git@github.com:getpelican/pelican-themes.git
Note that this repository uses sub-modules, so you need to use --recursive
when cloning. In order to pull the latest changes in the future, you need to do this:
cd pelican-themes
git pull --recurse-submodules
Once you’ve done this, you can try out the different themes by creating or changing the following setting in your pelicanconf.py
file:
# Which theme to use
THEME = '../pelican-themes/built-texts'
Just point this to a different theme folder and re-generate your site to see what it looks like. If you’re using the editing workflow mentioned above, just saving the file should rebuild the site automatically.
My theme was based on the theme called Built Texts. You can still see the family resemblance, but the two themes have diverged quite a bit.
I suggest that you try the different themes in the pelican-themes repository and either find one you like and stop reading, or find one you almost-sorta-like – and want to use as a base for your theme.
Forking or Copying to a New Theme
You now have some options - you can either fork the pelican-plugins
repository on github, then copy the theme folder you wish to start from and rename it - or you can just copy the theme folder somewhere else - such as your sites ./themes
folder, or a separate folder altogether - and work on it in it’s own git repo.
I’m not going to explain in depth how to use git or github here - they have excellent help documentation. If you want to
TODO:
The Structure of a Pelican Theme
You can find the minimum requirements for a working pelican theme here, but my theme expands on this a bit, to add extra features. The current structure of the blueprint theme looks like this:
├── themes
├── blueprint
├── static
│ ├── css
│ │ ├── fontello.css
│ │ ├── main.css
│ │ ├── print.css
│ │ ├── pygments.css
│ │ └── pygments-monokai.css
│ ├── font
│ │ ├── fontello.eot
│ │ ├── fontello.svg
│ │ ├── fontello.ttf
│ │ └── fontello.woff
│ └── js
│ └── html5.js
└── templates
├── analytics.html # Google Analytics snippet
├── archives.html # to display archives
├── article.html # processed for each article
├── article-sidebar.html #
├── article-sidebar-multipart.html # article sidebar snippets
├── article-sidebar-toc.html #
├── author.html # processed for each author
├── base.html # base page template
├── categories.html # list all the categories
├── category.html # processed for each category
├── colophon.html # colophon snippet for footer
├── disqus.html # disqus comments snippet
├── googleplus.html # google+ snippet
├── footer.html # footer snippet
├── index.html # the index (list all articles)
├── page.html # processed for each page
├── pagination.html # pagination snippet for index pages
├── period_archives.html # to display time-period archives
├── tag.html # processed for each tag
├── tags.html # list all tags; can be a tag cloud
└── twitter.html # snippet for twitter share button
Yes – I’m going to explain what all those are for.
The Main Theme Components
base.html

This is the main template - all the other ones inherit and extend this one, filling in the gaps with the appropriate output, depending on which page is actually being generated.
archives.html
This template
article.html
author.html
categories.html
category.html
index.html
page.html
tags.html
The Supporting Cast
These aren’t full templates - they don’t inherit the base template. They’re included in other templates to output certain reusable snippets of the site - the footer, the sidebar, etc…
article-sidebar.html
article-sidebar-multipart.html
article-sidebar-toc.html
analytics.html
colophon.html
This snippet is output on the right hand side of the footer. It’s a simple snippet and is conditional on a setting in your config file. It’s output currently looks like this:

and contains the following code:
{% if COLOPHON %}
<div class="colophon span5" id="colophon">
<h4 class="nav-header">{{ COLOPHON_TITLE }}</h4>
<p>{{ COLOPHON_CONTENT }}</p>
</div>
{% endif %}
You can then define the COLOPHON
variables in your pelicanconf.py
file, like this:
# Set Colophon variables, which can be output by the theme.
COLOPHON = True
COLOPHON_TITLE = 'About'
COLOPHON_CONTENT = '<a href="/pages/duncan-locks-resume.html">An adaptable...</a>'
Metadata & Microdata
Blueprint has extensive support for rich meta and microdata. Metadata like title
and description
have always been important for your site’s appearance in search results and for SEO generally - so the blueprint theme is very careful to provide complete support for all the traditional metadata - plus a few newer ones like favicons for phones & tablets.
In addition, Microdata is becoming more and more important and is increasingly being used by large services like Twitter, Google+ and, crucially, Google Search. Marking up your content with mircodata is a simple and unobtrusive way of adding machine readable metadata to your content - giving you an advantage when your content appears on services that can use this data.
The blueprint theme fully supports the following microdata:
Twitter Cards
Twitter cards make it possible for you to attach media experiences to Tweets that link to your content. Simply add a few lines of HTML to your webpages, and users who Tweet links to your content will have a “card” added to the Tweet that’s visible to all of their followers. – https://dev.twitter.com/docs/cards
This is what this looks like in action:

This is controlled by the following settings in your pelicanconf.py
file:
TWITTER_USERNAME = 'duncanlock'
TWITTER_ACCOUNT_ID = 'XXXXXXXXX'
TWITTER_CARD = True
Authorship
Google is piloting the display of author information in search results to help users discover great content. – https://support.google.com/webmasters/answer/1408986?hl=en
This is what this looks like in a Google Search result when this is setup and working:

Google In-depth Articles
This Google feature prefers articles which use schema.org Article microdata, specifically the following items:
- headline
- alternativeHeadline
- image
- description
- datePublished
- articleBody
See here for more information about Google In-depth articles.
Supporting image
also has other benefits, notably Google+ and Facebook, which will both default that image in as the thumbnail if you post a link:

Facebook & OpenGraph

Blueprint also supports OpenGraph metadata, for Facebook and other services which make use of it.
This is controlled by the following setting in your pelicanconf.py
file:
OPEN_GRAPH_METADATA = True
The Devil is in the Detail
Mention
A Multitude of Favicons
Put this into the <head>
section of base.html
:
{# Favicons #}
<meta itemprop="image" content="{{ SITEURL }}/static/images/favicon-128x128.png">
<link rel="shortcut icon" href="{{ SITEURL }}/favicon.ico">
<link rel="apple-touch-icon" href="{{ SITEURL }}/static/images/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="72x72" href="{{ SITEURL }}/static/images/apple-touch-icon-72x72.png">
<link rel="apple-touch-icon" sizes="114x114" href="{{ SITEURL }}/static/images/apple-touch-icon-114x114.png">
Google Analytics Integration
This goes into your publishconf.py
file:
# Output Google Analytics code
GOOGLE_ANALYTICS_ID = "UA-XXXXXXX-X" # <-- Replace with your Property ID
GOOGLE_ANALYTICS_UNIVERSAL = True
This goes at the bottom of base.html
:
{% include "analytics.html" %}
</body>
</html>
and analytics.html
looks like this:
{% if GOOGLE_ANALYTICS_ID %}
{% if GOOGLE_ANALYTICS_UNIVERSAL %}
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', '{{GOOGLE_ANALYTICS_ID}}', 'duncanlock.net');
ga('send', 'pageview');
</script>
{% else %}
<script>var _gaq=[['_setAccount','{{GOOGLE_ANALYTICS_ID}}'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script'))</script>
{% endif %}
{% endif %}
Plugins I use, which affect the theme
The theme expects some plugins to
webassets
- rearrange theme files
- first name in list of output is actual output filename
- use filename not query param for name
Future Plans
- Upgrade to Bootstrap 3
- Do I really need to be loading jQuery?
- Header snippet
- Move snippets into sub-folder & rename template files to .j2 instead of .html?
Footnotes & References:
SublimeText is currently my favourite text editor - it’s really pretty great, you should try it.]