Migrating from Wordpress to Pelican

Posted on February 22, 2014 in blog • 5 min read

I've finally taken the plunge and migrated from my old Wordpress.com site to my new and (hopefully) improved Pelican-built site! If you're reading this, you probably have two questions: "why?" and "how?"...so let's tackle them in that order.

Why? A lot of it comes down to the advantages that static site generators like Pelican have over the dynamic CMS that is Wordpress. Wordpress is without doubt a very powerful CMS, and it has a thriving, large community around it that adds on even more value to Wordpress through its huge collection of plugins. It's also really easy to setup and easy to use. So why switch to a static site generator like Pelican? Well, in return for giving up the convenience and usability that Wordpress offers, by adopting Pelican I got

  • speed: a static blog is going to be faster than a dynamically generated site, no matter how much you try to optimize your Wordpress site / cache / database. This site now serves up nothing more than HTML, CSS, and JS files.
  • simplicity (note: not convenience): as mentioned above, there's no need to set up, configure, and optimize your Wordpress installation. Simplicity in this sense also refers to the fact that this site is now powered by a smaller, simple to understand stack, rather than a giant and much more complex PHP stack that regularly attracts attackers...
  • improved workflow: you can use your preferred editor and your preferred VCS to create and keep track of your blog posts. Markdown is a nice bonus as well (it's the sweet spot between a WYSIWYG editor and raw HTML).
  • mobility/deployment: static site = easier to move around (just copy the files; there's no database to worry about) and deploy (and often cheaper to deploy; you can do so for free with Github Pages, for example).

Also, switching to Pelican means that I get to move off of Wordpress.com infrastracture, hence no more ads (and no need to pay $30/yr to get rid of them), no restrictions on the amount and type of content I upload, and being able to use my own domain name (without having to pay for it), and of course not having to rely on a third-party to host my blog.

As for "why Pelican and not any of the hundreds of other static site generators out there?"...because it's one of the most popular static site generators by far, and I know Python a lot better than I know Ruby (for me it came down to Pelican vs. Jekyll/Octopress). I know, these probably aren't very compelling reasons to pick Pelican over another static site generator, so feel free to experiment if you're planning on making the switch from Wordpress as well. An advantage of Pelican (and close competition like Jekyll) over the hundreds of obscure generators out there is that there's a sizeable community with an ample amount of themes, plugins, and support available, although if this was your main concern, you'd likely stick with Wordpress.

Switching over to Pelican had one major disadvantage for me, however:

Comments (or rather, the lack thereof).

Most static website generators "solve" this issue by making it easy to integrate your blog with Disqus. The only other alternatives come down to re-inventing Wordpress/Disqus' commenting systems (which kinda defeats the purpose of having a static site if you end up needing some sort of database and some PHP glue code to make everything work), or using a rudimentary email-powered solution whereby you get your readers to send you comments via email. I just ended up using Disqus, for lack of a better solution. commenting system.

Moving on to "How?" now...

Start by installing Pelican; there's a handy guide to getting started with Pelican available upstream, although if you're on Debian or a derivative, I suggest installing it via apt-get install python-pelican instead of using pip and virtualenvs as suggested by that guide. pelican-quickstart will ask you some questions to generate a set of config files populated with your answers. If you're migrating from Wordpress, make sure to export your data and convert it into a set of input files for Pelican with:

$ pelican-import --wpfile --dir-page -o content -m markdown wordpress.xml

Omit -m markdown if you prefer editing your blog posts in reStructuredText rather than Markdown. You can see the resulting Markdown/reST files in a content subdirectory.

At this point, you're ready to have Pelican generate a website for you (using the default theme and settings); pelican-quickstart will have generated a Makefile (as well as fabfile.py if you prefer Fabric instead) populated with a number of useful targets, e.g. make devserver to generate your site and host it on http://localhost:8000. You'll likely notice that the import script isn't perfect and you'll have to run through and fix a few things, but at this point you now have a working website which you can deploy via make publish and make {ssh,rsync,dropbox,ftp,s3,cf}_upload.

Pretty straightforward, no? (Almost) simple and quick enough to rival Wordpress' "famous 5-minute installation". ;)

At this point, you may want to browse through some of Pelican's plugins and themes. My site's current theme is a Svbtle-inspired theme closely based off of pelican-svbhack, with some minor modifications.

There are a number of settings that you'll want to tweak in pelicanconf.py, as well as publishconf.py (the latter is used only during make publish and inherits all the settings from the former, so you'll want to put most of your settings into pelicanconf.py). There is extensive documentation about each of the settings, so I won't go into too many details here.

As an example, by default Pelican generates all its output in a flat hierarchy, but you can easily force it to generate your site with a structure similar to Wordpress (like I've done with my site), with the following settings in pelicanconf.py:

ARTICLE_URL = '{date:%Y}/{date:%m}/{date:%d}/{slug}/'
ARTICLE_SAVE_AS = '{date:%Y}/{date:%m}/{date:%d}/{slug}/index.html'
PAGE_URL = 'pages/{slug}/'
PAGE_SAVE_AS = 'pages/{slug}/index.html'

If there are static files that you don't want Pelican to process, and just want to see copied over and placed alongside your generated HTML files, that's easy to accomplish as well. Just place them in a subdirectory of content, e.g. content/extra, and add the following settings:

STATIC_PATHS = ['extra']

...and those files will be copied to a subdir extra on your host. If you want to move them, e.g. to the top-level directory:

EXTRA_PATH_METADATA = {
    'extra/robots.txt': {'path': 'robots.txt'},
    'extra/favicon.ico': {'path': 'favicon.ico'},
}

(FILES_TO_COPY was deprecated in an earlier release, so avoid using that.)

Your theme and active plugins may also come with additional settings you can tweak inside your pelicanconf.py. Have fun!