Unconstant Conjunction A personal blog

Moving to Pelican

I recently moved the site over to Pelican. Although I liked Octopress, it wasn’t working exactly like I wanted it to, and I’m not comfortable enough working with Ruby to modify it. Since Python has become my go-to language for most things these days, it made sense to move to what seems to be the most popular static site generator written in that language. For posteriority’s sake, the following is a guide based on the steps I took to get it working. I’ve also included most of my configuration files and a short program for creating new posts.


First, you will need to install Python. Then, you will need pip, which is used to install third-party Python programs and modules. Once you have both of these, you can run:

$ pip install pelican

from a terminal. This shouldn’t take too long, since Pelican is written in pure Python and has few dependencies. Now, navigate to where you’d like to put your blog (say, the directory myblog) and run::

$ pelican-quickstart

This will ask you several questions. Generally, if you don’t understand the question, just answer n.

Configuration & Theme

My configuration file at the moment looks something like the following

AUTHOR = u'Aaron Jacobs'
AUTHOR_EMAIL = 'atheriel@gmail.com'
SITENAME = u'Unconstant Conjunction'
TAGLINE = u'most python and pcg'
DEFAULT_CATEGORY = 'Uncategorized'

# Feed generation is usually not desired when developing

# Social widget
SOCIAL = (('github', 'https://github.com/atheriel'),)


# Uncomment following line if you want document-relative URLs when developing

# Theme -- Pure Single
THEME = 'pure-single'
CSS_FILE = 'pure.css'
COVER_IMG_URL = 'http://dnqgz544uhbo8.cloudfront.net/_/fp/img/home/11.WVgzJf1Jz5x9uuR7KjWjXw.jpg'
PROFILE_IMG_URL = 'https://1.gravatar.com/avatar/eee1ad9206b3858a0ff49ade9983d8f4?s=128'
    ('About', '/pages/about-me.html'),
    ('Archives', 'archives.html')

I’m using a modified version of the Pure theme, which I’ve placed in the pure-single directory. Note that you’ll need to fill in the SITEURL with your own domain.

Creating New Posts

Unlike Octopress, Pelican doesn’t come with a prepackaged solution to creating new posts and pages. To remedy this, I whipped up a small program to do so, which I’ve also published as a gist. The script expects to reside in the root directory of your blog; the code should be pretty self-explanatory if you want to modify this, however. Notice that the configuration file above contains an “About Me” page – you can create one for yourself with:

$ python newpost.py 'About Me' --page

The full script is as follows. Note that it uses Docopt instead of the hell that is argparse, which you may need to install beforehand.

#!/usr/bin/env python

__doc__ = '''
Create a new post/page.

  newpost.py <title> [--page] [-t <tag>...]
  newpost.py -h | --help | --version

  --page           Create a 'page' as opposed to a 'post'.
  -t, --tags       Specify the tags for the page/post.
  -v, --version    Show version information and exit.
  -h, --help       Show this help and exit.

template = '''{title}

:date: {date}
:tags: {tags}
:author: {author}

import os
import sys
import os.path
import datetime 
from docopt import docopt

import pelicanconf  # To get the blog author

def main():
    args = docopt(__doc__)
    today = datetime.date.today()
    # Locate the blog directory and check that `content` exists
    cwd = os.path.dirname(os.path.realpath(__file__))
    assert os.path.exists(cwd + '/content')
    # Generate a file from title + date in the blog's content directory
    if not args['--page']:
        filename = os.path.join(cwd, 'content/{0}-{1}.rst'.format(today, args['<title>'].lower().replace(' ', '-').replace('.', '')))
        if not os.path.exists(cwd + '/content/pages'):
            os.mkdir(cwd + '/content/pages')
        filename = os.path.join(cwd, 'content/pages/{0}.rst'.format(args['<title>'].lower().replace(' ', '-').replace('.', '')))
    if os.path.exists(filename):
        print('Error: A file for that title already exists.')

    with open(filename, 'w') as f:
            title = args['<title>'],
            title_underline = '#' * len(args['<title>']),
            tags = ', '.join([t.lower() for t in args['<tag>']]) if args['<tag>'] is not None else '',
            date = today,
            author = pelicanconf.AUTHOR,

if __name__ == '__main__':
comments powered by Disqus