Pelican for Static Sites and Blogs

2   Summary

Pelican is a static site generator so it generates the html locally and then the site is served up as static HTML without the need for a database or development framework. It's written in Python using Jinja2, Pygments and Docutils.

It has the common blogging features:

  1. Dated blog pages using Restructured Text (RST), markdown or other mark-up languages
  2. Categories and tags
  3. Static pages
  4. Comments and trackbacks using an external service (Disqus)
  5. RSS and Atom feeds
  6. Syntax highlighting for source code listings
  7. File based so you can edit everything locally using your favourite editor
  8. Easily integrated with source control - Bzr in my case.

There's a good video introduction by Michael Crosby.

2.1   Alternatives

Jekyll is the static site generator that gathered the most interest. It's written in Ruby.

Hyde is an reimplementation of Jekyll in Python. I found it hard to identify if it was still an active project or not - though it's very popular.

Blogofile was my first choice but it's been going through a change as the main developer stopped working on it.

Soho is more of a traditional site creation tool, rather than being focused on creating a blog.

Rest2web similar to Soho this tool is focused on creating an entire site rather than a blog so it comes from an earlier generation.

3   Installation

The easiest way to install it is to use virtualenv and Pip. My installation is on Ubuntu 12.04 LTS with Pelican 3.0:

1. Create a virtualenv environment for it:

$ mkproject Pelican
(Pelian) $

This creates a virtualenv environment using the virtualenvwrapper commands creating a project directory for you (due to my set-up this is ~/workspace/Pelican) and moving you into it. You know it's been successful because your command prompt now changes to show you that you're in the created virtualenv.

2. Install Pelican itself:

(Pelican) $ pip install pelican
# It does a lot of things!

This uses Pip to install Pelican along with any dependencies that it requires. There are quite a few and you can list what's in the system with 'lssitepackages' to get an idea.

3. Create a basic Pelican site:

(Pelican) $ pelican-quickstart

It asks you a bunch of questions to set-up the site for you properly.

4. Create a test post
You have to create a test post to make sure everything is fine.
5. Create some basic html

To test that HTML generation is working properly use:

(Pelican) $ make html

6. Start the development server You can start the development server and enable it to regenerate content any time it sees any changes with:

(Pelican) $ make devserver

You can now browse to http://127.0.0.1:8000 to see the test content.

Note

You may need to edit develop_server.sh, due to an issue, to add:

PWD="/bin/pwd"
BASEDIR=$($PWD)

4   Basic Set-up

Having got the basic demonstration site up and running you can configure it to meet your needs.

4.1   Structure

Inside the source directory there are some files:

pelicanconf.py
This is the main configuration file which tells Pelican how everything works.
Makefile
This is a Makefile you can use to manage the environment.
develop_server.sh
This starts the development server which will recompile the contents if you make any changes.
content/
This directory is where you put all your posts.
output/
This directory is where the processed HTML files go.

There's no templates, themes or extensions folder by default.

4.2   Basic Pelicanconf settings

These are stored in pelicanconf.py by default. These are the basic settings that come with the system, for more advanced settings see Configuration further down:

AUTHOR = u"Steve George"
SITENAME = u"Futurile"
SITEURL = 'http://www.futurile.net'

# http://pelican.notmyidea.org/en/latest/settings.html#timezone
TIMEZONE = 'UTC'
DEFAULT_LANG = 'en'

# Blogroll
LINKS = ( ('Pelican', 'http;//docs.myidea.org/alexis/pelican/'), ('Python.org', 'http://python.org'), )

# Social widget
SOCIAL = ( ('You can add links here', '#'), )

DEFAULT_PAGINATION = 10
REVERSE_ARCHIVE_ORDER = True

5   Writing Posts

Blog posts and content are written and stored in the 'content' directory by default:

Example blog page
------------------
:title: This is an example title
:date: 2010-10-03 10:20
:tags: thats, awesome
:category: yeah
:author: Alexis Metaireau
:excerpt: This is a short description.

Here is some content.

5.1   Storing posts

If you do not specify a category then Pelican will use the directory structure to work out what the category should be. Equally if you don't specify a date then Pelican will use the files mtime to work out the date for you.

5.2   Post header

The header itself uses YAML, it is the portion between the -- lines.

:title: <some title>
A one line title for the post. Alternatively, you can just put it at the top of the file like a normal RST doc.
:date: <date>
The date the post was last updated (year/month/day hour:minute:second)
:category: <category name>
A name for the category, and there can only be one which is different to wordpress where you can have multiple. By default this is shown in the top menu.
:tags: <comma list>
A comma list of tags.
:slug: <title-that-will-be-used-for-permalink>
Essentially, this is the permalink that it will use rather than detecting for itself.
:author: <name>
The author of the post.

5.3   Post content

The post content can be in either RestructuredText with a file extension of .rst, or in Markdown with a file extension of md.

If you'd like a post to be a draft then you can set this in the metadata, it will then be published to drafts folder:

:status: draft

Note that by default it just puts these into a URL which is the same as the top of the site. So if you create a post with a title of test2 and set the status to draft it will appear as http://mysite.com/test2.html though it will not be linked in the navigation.

5.4   Pages

If you'd like static pages for the site then you create a directory under your content directory called pages and put the files in there. The content itself can look like a normal RST post.

To enable the pages to show on the menu you have to edit pelicanconf.py with the following setting:
DISPLAY_PAGES_ON_MENU = True

If you're creating error pages then you can use the metadata to hide them:

:status: hidden

You could use this for a 404 page for example.

5.5   Syntax highlighting

Pelican comes with syntax highlighting set-up using Pygments which is one of the dependencies it set-up during install. If you're using RST, then to display a code fragment you use:

.. code-block:: python

        print "This is an example code block"
        # The code block starts with a blank line and ends with a blank line

You can also over-ride pygments so that you can use your own theme.

6   Building & Testing

6.1   Makefile

There's a default Makefile which you can use to generate the files and put them into the output directory:

(Pelican) $ make html

If you want to clear all the generated files then use:

(Pelican) $ make clean

To serve the output on your machine locally you can use:

(Pelican) $ make serve

This starts a local server which you can browse to on 127.0.0.1:8000

A neat feature is the ability for Pelican to regenerate itself automatically when it sees a change in the content directory. This enables you to make changes and then Pelican will automatically update your running test server without you have to issue the commands. To do this you have to run:

(Pelican) $ make devserver
In the stable release I'm using an edit to the devserver script was required, see:
https://github.com/getpelican/pelican/issues/473

To stop the running server you can then do:

(Pelican) $ ./develop_server.sh stop

7   Publishing

After you've finished writing some content it's time to publish the results. You can use the Makefile as it has a variety of options.

By default there are two configuration files. We edited pelicanconf earlier which we used for our local development. The one for publishing is publishconf.py so you have to edit this to give it similar settings. See the URL settings section for more info.

So, after regenerating the content with the 'production' settings you can then copy the content directory to your host.

Blogging with Pelican and GitHub
Martin Brochhaus runs through how he blogs using Pelican and Github to publish the pages.

7.1   Publishing with Fabric

I'm using Fabric to publish my content. The short fabfile.py that I have is:

import os
from fabric.api import *
import fabric.contrib.project as project

BASEDIR = os.path.abspath(os.path.curdir)
OUTPUTDIR = os.path.join(BASEDIR, 'sitebuild')
CONFFILE = os.path.join(BASEDIR, 'publishconf.py')
env.hosts=["XXX@myserver.com"]

def build():
        """ Build the site for publishing """
        local('pelican --output {} --settings {}'.format(OUTPUTDIR, CONFFILE))

def publish():
        build()
        project.rsync_project(
                local_dir="~/workspace/Pelican/sitebuild/",
                remote_dir="/users/home/web/public",
                exclude=("*_local.py", "*.pyc",)
                )

8   Advanced configuration

Common configuration settings:

# The default author for pages
AUTHOR = u"Steve George"

# The default date format expected
DEFAULT_DATE_FORMAT = '%d %m %Y'

# Show Pages on the main menu bar
DISPLAY_PAGES_ON_MENU = True

# You have to install rst2pdf for this to work
PDF_GENERATOR = True

# The name of the site used on the mane page
SITE_NAME = u"Futurile"

# The name base site URL used in creating feeds: this should be without a trailing slash
SITE_URL = 'http://www.futurile.net'

# Sets it so that oldests posts are shown first - the default?
REVERSE_ARCHIVE_ORDER = True

REVERSE_CATEGORY_ORDER = True

# The timezone that your working in, taken from http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
TIMEZONE = 'Europe/London'

THEME = '../blah/theme'

8.1   Pelicanconf Example

The Pelicanconf.py that we're using lands up looking something like this:

#!/usr/bin/env python
# -*- coding: utf-8 -*- #

AUTHOR = u"Steve George"
SITENAME = u"Futurile"
SITEURL = 'http://www.futurile.net'
TIMEZONE = 'Europe/London'
DEFAULT_LANG = 'en'
DEFAULT_PAGINATION = 10

# Extensions
#TYPOGRIFY = True
#LESS_GENERATOR = True

MENUITEMS = (('About', 'about-me/'),
                        ('Reading', 'reading/'),
                ('Archive','archives.html'),)

# Blogroll
#LINKS =  (('Pelican', 'http://docs.notmyidea.org/alexis/pelican/'), ('Python', 'http://python.org'), ('Jinja2', 'http://jinja.pocoo.org'), ('UKClimbing', 'http://ukclimbing.com'),)

# Social widget
SOCIAL = (('Twitter', 'https://twitter.com/#!futurile') ,)

# Enable pages in the menu
# Set clean urls for pages as well
#DISPLAY_PAGES_ON_MENU = True
PAGE_URL = '{slug}'
PAGE_SAVE_AS = '{slug}/index.html'
#PAGE_URL = '{slug}.html'
#PAGE_SAVE_AS = '{slug}.html'
#PAGE_LANG_URL = '{slug}-{lang}.html'
#PAGE_LANG_SAVE_AS = '{slug}-{lang}.html'

# This sets the location of the pages - creating clean urls
ARTICLE_SAVE_AS = '{date:%Y}/{date:%m}/{date:%d}/{slug}/index.html'
ARTICLE_URL = '{date:%Y}/{date:%m}/{date:%d}/{slug}/'
# Puts the blog articles into reverse order, most recent first - default for blogs
REVERSE_ARTICLE_ORDER = True

# Theme
#THEME = './src/themes/svbtle'
#THEME="pelican-svbtle"
#THEME="notmyidea"
THEME="subtle"

#from pelican.plugins import related_posts
PLUGINS = ['pelican.plugins.related_posts',]

# Tag cloud
# Doesn't seem to do anything
TAG_CLOUD_STEPS = 4
TAG_CLOUD_MAX_ITEMS = 50

# RSS & Atom
#FEED_DOMAIN = SITEURL
#FEED_RSS = 'feeds/rss'
#CATEGORY_FEED_RSS = 'feeds/category/.%s.rss'
#FEED_URL = 'http://feeds.feedburner.com/Futurile'
FEED_DOMAIN = SITEURL
TAG_FEED_RSS = None
#CATEGORY_FEED_ATOM = 'feeds/%s.atom.xml'
FEED_ATOM = 'feeds/all.atom.xml'

# static paths will be copied under the same name
STATIC_PATHS = ["images", ]

# A list of files to copy from the source to the destination
FILES_TO_COPY = ( ('robots.txt', 'robots.txt'), ('images/favicon.ico','favicon.ico'),)
MENUITEMS = ( ('Archives', '{0}/archives.html'.format(SITEURL)), )

###################################################
#     Theme specific
####################################################
# Extensions
# GOOGLE_ANALYTICS = 'XXXXXXX'
# DISQUS_SITENAME = 'yourdisqushandle'
# GITHUB_URL = 'http://place-at-github'
# TWITTER_USERNAME = 'username'

8.4   Feedburner

In Feedburner set the following:
Original Feed Feed Address

8.5   Static files

Robots.txt

User-agent: * Disallow: /theme/ Disallow: /tag/ Disallow: /uploads/

8.6   Images

By default it copies across the 'images' directory.

8.7   Typogrify

This is a set of filters that improve the way in which text is displayed. There's nothing major but it does nice things like stopping titles run over multiple lines when there's just one word on the second line.

To enable it you need to install typogrify and set it as on in the Pelicanconf file:
$ pip install typogrify
Add the line to Pelicanconf:
TYPOGRIFY = True

8.8   Less Generator

If you would like to use less css

First install Less:

(Pelican) $ pip install lesscss
Alter the Pelicanconf configuration file to include:
LESS_GENERATOR = True

8.9   Controlling URL Publishing

Controlling the URL's that things are actually published too.

We ideally want a format which is something like this:
http://www.futurile.net/2012/09/22/article-title/

The 'slug' bit is a short description in the blog post which describes the post

FIXME: I can't get this to work

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

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

See: http://blog.aclark.net//2012/09/22/sorry-for-the-blog-spam/

9   Themes

There's a themes repository which has most of the common themes in it. There's also a pelican-themes command that you can use the manipulate themes.

Pelican-themes is a command line tool to manage themes in Pelican:

$ pelican-themes --list

Get a theme either through git, or downloading it. This pulls down the pelican themes repository:

$ git clone https://github.com/getpelican/pelican-themes/

Install the theme:

$ pelican-themes --install --verbose /location/of/theme

Removing a theme:

$ pelican-themes --remove <name of theme>

In the future you'll be able to upgrade a theme:

$ pelican-themes --upgrade

9.1   Notmyidea

This is the default theme that is generated when Pelican creates the initial site, you can see what it looks like on Alex Metaireau's site. It has some specific settings that you can put into the Pelicanconf file:

# Sitename from Disqus
DISQUS_SITENAME

# Google Analytics page
GOOGLE_ANALYTICS = 'XXXXX'

# A list of tuples (Title, URL) for additional items to appear in the Menu
MENUITEMS

LINKS

SOCIAL

9.2   Pelican-svbtle

Pelican-svbtle is a really nice theme when you see it on his site, but I found it a bit difficult to use.

First you need to make a directory to clone the theme into. I'm going to use the pelican-themes app, so the theme itself is installed in Pelican. So I don't need the directory to be in my 'content' location, it can be in the top-level dir of the site:

(Pelican) $ mkdir themes

I clone the git repository:

git clone https://github.com/wting/pelican-svbtle

I install the theme in pelican using:

pelican-themes --install themes/pelican-svbtle/ --verbose

It copies it to Pelican/local/lib/python2.7/sitepackages/pelican/themes/pelican-svbtle

Edit your Pelican configuration file to refer to the pelican-svbtle theme:

THEME = "pelican-svbtle"

I had problems with using it but you get the idea.

To remove it you use:

$ pelican-theme --remove pelican-svbtle

9.3   Subtle

The Subtle theme is really well documented so worth playing around with, it's quite advanced.

Clone the Pelican git repository:

git clone https://github.com/getpelican/pelican-themes

Install the theme as follows:

pelican-themes --install themes/pelican-themes/subtle --verbose

Edit your configuration file to refer to the subtle theme.

9.4   Bootlex

Bootlex is an alternative, there's no example of it so I haven't tried it.

9.5   Bootstrap2

Bootstrap 2 is a nice theme. Alex Sulfrian's site uses this theme.

9.6   Dev/random

Dev/random focuses on a simple layout and font set-up, an example site is this one.

9.7   Notmyidea-CMS

I'm not sure what the specific differences are between Notmyidea-CMS and the normal Notmyidea.

9.9   Amazium

Amazium is using responsive design so if you scale the site down to how it would look on a phone it folds everything up for you nicely.

9.10   Rach

Rach is a really nice theme that Rach Belaid used for his site. It looks completely different, to my eyes, from many of the other Pelican blogs so I like it.

10   Creating your own theme

Pelican uses Jinja2 templating engine to output the HTML. Start with the simple theme if you want to create your own theme.

The basic directory structure consists of a static directory and a templates directory. In the statics directory there's a subdirectory for css and a subdirectory for images. Then there is a templates directory which has all the templates that will be used to create the HTML. So structure looks like this:

|--static
|    |---css
|    |---images
|
|---templates
|

The mandatory templates in the templates directory are:

archives.html
article.html    ---> Rendered for any blog post
authors.html
base.html               ---> Rendered for all other templates
categories.html
category.html
index.html              ---> Rendered for any index.html
page.html
tag.html
tags.html

10.1   Static

The main elements I played with are:

main.css                ---> used by the site
pygments.css    ---> used by pygments for code
typogrify.css

10.2   Basics

Each template receives all the variables that are defined in capitals in the settings file. For example the SITEURL is specified in the conf file so you can access this. Other than that, it's just a matter of going through the templates and playing around with everything.

More information on creating a theme in the documentation, and there's a great Macdrifter post.

10.3   Installing your own theme

Find out where your themes are:
$ pelican-themes --path
Copy the one you want to play with to somewhere you can mess with it
$ cp <long/path/from/above> themes/simpletest
Install the altered theme by editing your Pelicanconf.py
THEME = "themes/mycustomtheme"

11   Import from wordpress.com

In another terminal you have to install a system wide pandoc as it's not covered by Pip:

$ sudo apt-get install pandoc

Install pandoc and BeautifulSoup:

(Pelican) $ lssitepackages
# Check to see if BeautifulSoup or pandoc are installed
(Pelican) $ pip install BeautifulSoup
Login to wordpress.com and do an export of your posts. They'll be downloaded as an xml file.
Import posts as one file Import pages as another file

Run the pelican-import utility:

$ pelican-import --wpfile futurile.wordpress.xml -o wordpresstest

This outputs all the files to wordpresstest location. You then have to go through them all altering them so that they work correctly!:

$ rst2html --generator --date --strip-comments --verbose --footnote-reference=superscript [inputfile] [outputfile.html]

Then edit the contents by hand to fix any issues.

12   User Blogs

Other blogs that use Pelican are:

12.1   Bunnyman

His site bunnyman.info has some good articles and you can see the source of his site on github.

12.2   Pydanny

The pydanny site is on gihub, where you can also find the source.

12.3   Chippedprism

Chipped prism has some nice content.

18   Resources

Getting started with Pelican
This is the official documentation that comes with Pelican. It's pretty good, though I found some bit unclear.
Blogging with Pelican and GitHub:
Martin Brochhaus' post on how to use Pelican with Github pages.
Pelican: A static blog generator for Pythonistas
F Javier covers all the main reasons why you'd use a Python based static blog generator.
Yes, this blog is now powered by Pelican
Alan Clark writes a good post on why he's using Pelican.
Pelican Guide - Moving from WordPress and Initial Setup
Extensive guide on how a complex Wordpress set-up was migrated across to Pelican. Including how to set-up a Google site map.
Blogging with Pelican and GitHub
Martin discusses how he uses Pelican and Github. This is a great step-by-step guide.
Moving to Pelican
Tarek moved to Pelican pretty early but he outlines his experiences.
Stackoverflow Pelican Questions
Pelican questions in Stackoverflow.
Blogging with Pelican
Extensive blog post on how to use Pelican.
Pelican Bootstrap theme
Aziz Bookwala's updated responsive theme for Pelican.
Pelican on Ohloh
Ohloh project summary for Pelican