I’ve been blogging for a while. First with LiveJournal, then various incarnations of Wordpress. At this point, I feel like it’s time to consolidate a little and have a static website. This post explains some of the benefits and pitfalls of moving to a static website via Pelican, versus the very popular Wordpress.

Why not Wordpress?

Wordpress is great. It is being constantly updated and tweaked. This is a blessing and a curse, however. The platform progresses at a decent pace, but all the periphery concerns like themes and plugins… they may not. I’ve maintained enough Wordpress sites for myself and others to be well aware of the endless treadmill of updates, the occasional lock-out because of a misbehaving plugin, or being hacked because a theme goes rogue or stale.

I think Wordpress is ideal for those who will get enough traffic and interest that the maintenance side is worth it. These are typically sites with a lot of churn in content and readers. My blogs are not that. It makes sense to scale it back to a simpler site where I can run several sites under the same server footprint as one Wordpress blog.

What’s the alternatives?

You can pare it right back and just have a very static website, handcrafted and unchanging. HTML isn’t too hard, and if you’re willing to use a bit of PHP, you can template much of it. This is how I used to do my personal website.

Of course as you grow more and more against the boundaries of this, you’re leading towards the static site generators. These take files written in a plain text format, include that content into a theme and bake it all into static HTML files. There are some popular choices:

I personally chose Pelican because it had a mature-enough library of themes and plugins, and was written in Python so I could hack it to bits if I wanted to. But wait, why worry about themes and plugins if I left Wordpress to avoid all that?

Static site generators run all the code once, on your computer. All the code applied is what you have on your machine. Once the site is generated, there’s much fewer potentially exploitable security holes since the site no longer dynamically includes data. It just serves up HTML pages. It’s like handcrafting your website, but automating away the busywork like creating category pages and indices, making nice URLs, and moving media content around.

Static sites are also useful in conjunction with CDNs - services that will cache your content closer to your readers. Since your site is static, it’s easier for them to keep good caches and fire your content at them at high speed.

The different static site generators all work similarly except for small details. To update your website:

  1. Build the site: This collects all the content, builds temporary structure and links, and bakes everything into templated HTML.
  2. Upload the site: Copy a directory directly to your web server.

We’ll look at doing this for Pelican.

Using Pelican

Installing pelican is super easy:

pip install pelican

There are only-slightly more complicated instructions in case you want to install pelican in a virtual environment, or using the bleeding-edge version of the code.

To prepare your website, create a directory for it and just run:


This prepares a number of scripts and folders for you under that main folder. This can set up details like where to publish the site via SSH or FTP, and what RSS/Atom feeds to generate. More details can be found in the Pelican publishing documentation.

The next tricky thing is customizing the site as you want it. In your main folder is pelicanconf.py. This is a Python file where you set global site variables like they are Python variables.

For example, the first few lines of my pelicanconf.py:

AUTHOR = 'Brett Witty'
SITENAME = 'Facets of BrettW'
SITESUBTITLE = "Exploring the technical arts"
SITELOGO = 'images/hacker-hs.png'
TIMEZONE = 'Australia/Canberra'

The default pelicanconf.py is easy to read and modify. The defaults are sane, but it’s easy to modify them to match your tastes.

Writing content

To create content you just add files to the content/ subdirectory. Pelican supports Markdown and ReStructuredText, which you can write in almost any text editor. There’s basic formatting like headings, lists, links and media files. I’ve set mine up to accept org-mode format as well.

You add metadata like the post title, tags and category by adding some text at the start. For example, this post’s metadata in Markdown:

Title: How to move your website to Pelican
Date: 2017-12-27
Author: brettw
Category: Technical/How To
Tags: blogging
Slug: how-to-move-to-pelican
Status: published
Summary: Looking to move from Wordpress to a static site? Learn from my journey!

Most of that is optional but is nice for organization. I know I filled out much the same data for Wordpress posts, so it’s not an extra burden!

You can also write plain HTML files and just have it work nicely. There are ways to set metadata for them such that they link and categorise like all other content.

Non-chronological content like pages are created just as easily. Just have a content/pages/ directory and they get treated accordingly.


Every web platform comes with some theming. The default ones for Pelican are nice, but creating your own is straightforward if you are familiar with Jinja2 templating. I was rusty on Jinja2 but it’s similar to Python, so I found a theme I mostly liked and figured out how to hack it to my whims.

Browse the official list of pelican-themes and see if anything takes your fancy.

Setting the theme is as simple as adding these lines to your pelicanconf.py:


The theme may read in extra variables so you can turn on or off theme parts. These are set in pelicanconf.py as well. And don’t forget: this file is Python so you can run some cool code to set variables if you like.

You can switch themes very readily, in case you want to change them with the seasons.


Out of the box Pelican has a solid but small list of capabilities. If you want to add things like sitemaps or rendering mathematics, you need plugins. Same as Wordpress, but these are only running at compile time.

There’s an array of plugins at pelican-plugins. I must admit, some have better capabilities and documentation than others. Installing them is as simple as cloning the plugin into a plugins subdirectory and in your pelicanconf.py:

PLUGIN_PATHS = ['plugins']
    # ...

Turning off a plugin is as simple as commenting out the line that includes it here, and rebuilding.

Moving from Wordpress

Pelican comes with an import tool that will read WordPress, Tumblr and other files, and convert them into the right format for your site. And it does it non-destructively so that you can add the converted files as you like.

In WordPress you go to your dashboard, Tools -> Export. Export all content and save that file off as a giant XML file. Then to import:

pelican-import --wpfile -o converted_dir -m markdown --wp-attach blog.xml

Running through the options:

  • --wpfile says that blog.xml is a WordPress export.
  • -o converted_dir is where you want to put the imported files.
  • -m markdown specifies that you want the format to be Markdown.
  • --wp-attach will download all referenced attached files and put them with their imported files.

If you used any funky HTML formatting or WordPress plugins, you may want to run your eyes over each imported file. I had to do so with my RPG posts, just to make sure they looked good. pelican-import has a --strip-html option to remove anything it doesn’t know how to convert, in case you need it.

Building, testing and uploading

Building the site is also pretty simple:


This will churn through PATH (content/) and put the website in OUTPUT_PATH (output/).

If you want to check out the site locally, just:

cd output/
python3 -m python.server

and browse to localhost:8000. If you run pelican -r, it will watch your website directory and rebuild if there are any changes.

If you used the pelican-quickstart it offered the ability to create Makefiles for easy builds. make html will run Pelican to compile the site. By filling in a few variables, I set mine up so building and deploying my site is as easy as:

make rsync_upload

This builds and copies the site to the server, assuming everything went well.

Tips and tricks

  • Categories don’t work like they do in WordPress. A post can have at most category, but as many tags as they like. This may take some fiddling if you import from WordPress.
    • If you want hierarchies of subcategories there is a subcategory plugin, but I found it slightly tricky to set up.
    • Tags are the same ignoring case, but are sensitive to punctuation and space.
    • Tags and categories can have the same names.
    • There’s no easy way to extract the tags and categories to do any gardening on them, except by viewing them through your website.
  • If you want to improve the markdown experience, add a few standard extensions. I also recommend PyMdown extensions to supercharge your Markdown.
  • Org-mode support is supplied by the org_reader plugin. It has quirks and fairly minimal documentation.
  • If you have the time, patience and perfectionism and are moving a WordPress blog to Pelican, I recommend examining each page. I trimmed out a lot of posts as they were of no use to anyone, and improved the ones I did still want.
  • Other people have made similar blogs: