Migration from WordPress to Pelican

Migration feedback of a WordPress blog to a static site built with Pelican.

Why ?

I just want a lightweight site. I tried to keep my WordPress instance clean but it has so much features I didn’t use that the tool was not meeting my needs. My shared hosting was not helping either and I was not satisfied by the average page loading time.

As I was already writing all my content with Markdown outside the Wordpress editor, I decided to go for a static site generator.


Pelican is a static site generator written in Python. It supports Markdown, AsciiDoc and reStructuredText.
There is a lot of similar tools, and you certainly knows Jekyll or Octopress.
I choose Pelican because it has translation available out of the box. You can get it with others but not natively.


For OS X:

brew install python
pip install virtualenv

## Install Pelican
mkdir -p ~/virtualenvs/pelican
virtualenv ~/virtualenvs/pelican
cd ~/virtualenvs/pelican
. bin/activate
pip install pelican
pip install Markdown
pip install beautifulsoup4
pip install typogrify
pip install webassets
pip install cssmin

For others OS installation details are here.

Activate Pelican environment

. ~/virtualenvs/pelican/bin/activate

Quit Pelican environment


Create a site

Launch pelican-quickstart and follow instructions.

Welcome to pelican-quickstart v3.3.0.

This script will help you create a new Pelican-based website.

Please answer the following questions so this script can generate the files
needed by Pelican.

> Where do you want to create your new web site? [.] blog
> What will be the title of this web site? Jean-Christophe Gay
> Who will be the author of this web site? Jean-Christophe Gay
> What will be the default language of this web site? [en] fr
> Do you want to specify a URL prefix? e.g., http://example.com   (Y/n) Y
> What is your URL prefix? (see above example; no trailing slash) http://jeanchristophegay.com
> Do you want to enable article pagination? (Y/n) Y
> How many articles per page do you want? [10]
> Do you want to generate a Fabfile/Makefile to automate generation and publishing? (Y/n) Y
> Do you want an auto-reload & simpleHTTP script to assist with theme and site development? (Y/n) Y
> Do you want to upload your website using FTP? (y/N) N
> Do you want to upload your website using SSH? (y/N) N
> Do you want to upload your website using Dropbox? (y/N) N
> Do you want to upload your website using S3? (y/N) N
> Do you want to upload your website using Rackspace Cloud Files? (y/N) N
Done. Your new project is available at /Users/jcgay/blog

Generated sources:

├── Makefile
├── content
│   ├── (pages)
├── develop_server.sh
├── fabfile.py
├── output
├── pelicanconf.py
└── publishconf.py

2 directories, 5 files

Add content

Articles must be saved in content folder.
You can extract your WordPress articles using Pelican importer: http://docs.getpelican.com/en/3.3.0/importer.html#import

I have not tried it, I already had Markdown version of my content. It was just a matter of adding necessary metatada in each of my .md file.

To have an article recognized by Pelican, add metadata:

Title: git-p4 au secours de Perforce
Date: 2012-03-18 18:10
Category: Scm
Tags: git, git-p4, perforce, p4
Slug: git-p4-au-secours-de-perforce
Author: Jean-Christophe Gay
lang: fr

slug property allow to customize URL generated by Pelican. This way you will be able to keep your WordPress URL.

Choose a theme

Themes are available in the repository https://github.com/getpelican/pelican-themes.

For now I use elegant.

Clone the repository to have it accessible by Pelican configuration.


Pelican is extendable by picking plugins. They are listed in the repository https://github.com/getpelican/pelican-plugins. Clone it.

Here are the active plugins on my installation:

  • sitemap: generate sitemap.xml file.
  • tipue_search: search engine for your content without using a third party service.
  • extract_toc: extract a table of contents.
  • optimize_images: compress jpeg and png images.
  • related_posts: display other articles in relation with the current one.
  • summary: set a summary limit using <!-- PELICAN_END_SUMMARY --> directly in article.
  • assets: compile/minify static resources.


Configuration is split in two files: pelicanconf.py et publishconf.py. The last one override former configuration with the production settings.

Parameters are described here.

I have not met any difficulties, two tips anyway.

  1. Generate clean URLs:

    ARTICLE_URL = '{slug}'
    ARTICLE_SAVE_AS = '{slug}/index.html'

    A folder slug is created for each article containing a single index.html file.

  2. Copy files using metadata EXTRA_PATH_METADATA :

        'extra/humans.txt': {'path': 'humans.txt'},
        'extra/robots.txt': {'path': 'robots.txt'},
        'extra/.htaccess': {'path': '.htaccess'},


If you were using WordPress comments, you must move them to a third party service like Disqus.
I was already using it, if you’re not, install this plugin.

In each article, add expected discussion feed identifier:

disqus_identifier: 7 http://jeanchristophegay.com/?p=7

It is read by elegant theme.

Redirect rules

Rewrite URLs which will disappear.

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule feed/?$ feeds/rss.xml [R=301,L]
RewriteRule wp-content/uploads/2013/03/Capture-d’écran-2013-03-09-à-11.24.20-300x182.png images/p4merge-mini.png [R=301,L]
RewriteRule wp-content/uploads/2013/03/Capture-d’écran-2013-03-09-à-11.24.20.png images/p4merge.png [R=301,L]
# Redirect wp-content/uploads/2012/03/git-p4.png to images/git-p4.png
RewriteRule wp-content/uploads/[0-2][0-9][0-9][0-9]/[0-1][0-9]/([^/]+) images/$1 [R=301,L]
# Redirect 2012/04 to archives.html#2012
RewriteRule ([0-2][0-9][0-9][0-9])/[0-1][0-9]/? archives.html#$1 [R=301,NE,L]
# Redirect category/slug/ to categories.html#slug-ref
RewriteRule category/([^/]+)/? categories.html#$1-ref [R=301,NE,L]
# Redirect tag/slug/ to tags.html#slug-ref
RewriteRule tag/([^/]+)/? tags.html#$1-ref [R=301,NE,L]
# Redirect author/jcgay/ to /
RewriteRule author/jcgay/? / [R=301,L]

Test/Publish site

To generate site, launch make html && make serve.
Content is generated into output folder and publish at http://localhost:8000.

Production site should be generated using make publish. Upload the whole thing.


I like the final result, my blog is now generated from a simple git repository, content is versionned and the whole process is less cumbersome that what I was used to. Mission accomplished !

comments powered by Disqus