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.
Installation
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'
SITEURL = ''
TAGLINE = u'most python and pcg'
DEFAULT_CATEGORY = 'Uncategorized'
DEFAULT_LANG = u'en'
SUMMARY_MAX_LENGTH = 120
# Feed generation is usually not desired when developing
FEED_ALL_ATOM = None
CATEGORY_FEED_ATOM = None
TRANSLATION_FEED_ATOM = None
# Social widget
SOCIAL = (('github', 'https://github.com/atheriel'),)
DEFAULT_PAGINATION = 5
# Uncomment following line if you want document-relative URLs when developing
RELATIVE_URLS = True
# 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'
MENUITEMS = [
('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.
Usage:
newpost.py <title> [--page] [-t <tag>...]
newpost.py -h | --help | --version
Options:
--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}
{title_underline}
: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('.', '')))
else:
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.')
sys.exit(1)
with open(filename, 'w') as f:
f.write(template.format(
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__':
main()