PE

Pelican

Static site generator for Python and Markdown lovers

Blogging Platforms ★ 13.3k stars Medium setup AGPL-3.0

Pelican is an open-source static site generator written in Python that builds blogs from Markdown or reStructuredText. It supports themes, plugins, and import from other blogging platforms.

Key features

  • Markdown and reStructuredText
  • Theme and plugin support
  • Import from WordPress and others
  • Atom and RSS feeds

Pros & cons

Strengths

  • Great for Python users
  • Mature and stable

Trade-offs

  • No admin UI
  • Python environment needed

Pelican replaces

Last reviewed Aug 26, 2026 · 808 words

Pick Pelican if you write Python and Hugo if you do not. That is the whole decision for most people, and it is not a knock on Pelican: after 16 years it is the most mature Python static site generator, and its edge over the Go and JavaScript competition is that its plugins and themes are Python you can read, patch and write in an afternoon. If that edge means nothing to you, Hugo builds faster and installs as one binary. If it does, Pelican is a very comfortable home for a blog.

The advantage is plugins you can actually change

Pelican's plugin system is plain Python: a plugin subscribes to signals such as article_generator_finalized and gets handed the article objects. A reading-time estimate, a custom feed, a related-posts block that uses your own scoring: each is 30 lines, not a fork of the generator. The pelican-plugins organisation on GitHub publishes the common ones (sitemaps, search indexes, image processing) to PyPI, installable with pip. Enabling one is pip install pelican-sitemap followed by adding "sitemap" to the PLUGINS list in pelicanconf.py, and if that list is absent, installed plugins are picked up automatically. Themes are Jinja2 templates, the same engine Flask uses, so a Pelican theme reads like the templates in any Python web app you have already worked on.

Quickstart to first post in five commands

python3 -m venv ~/.venvs/pelican && source ~/.venvs/pelican/bin/activate
pip install "pelican[markdown]"
mkdir ~/blog && cd ~/blog && pelican-quickstart
pelican content -o output -s pelicanconf.py
pelican --listen

pelican-quickstart asks a dozen questions (site name, URL, timezone, whether to generate a Makefile) and writes pelicanconf.py and publishconf.py. Posts go in content/ as Markdown with a small metadata block at the top:

Title: Why I moved off WordPress
Date: 2026-08-26
Category: self-hosting
Tags: pelican, static

pelican --listen serves the output on port 8000, and adding -r rebuilds on save. Atom feeds are generated by default; FEED_ALL_ATOM and its siblings in the config control the paths. The catalogue's Medium difficulty is fair: nothing here is hard, but every step assumes you are comfortable with a Python virtual environment and a terminal.

The WordPress import works, with pandoc doing the heavy lifting

Export your WordPress site as WXR XML, then:

pelican-import --wpfile -o content --markup markdown export.xml

pelican-import needs pandoc installed to convert HTML to Markdown. Posts, dates, categories and tags come through; comments do not, and neither do media files, which you copy from wp-content/uploads into content/images and fix the paths for. Budget an hour of cleanup per 50 posts for shortcodes and embedded HTML that pandoc translated literally. The same tool imports Blogger, Dotclear, Tumblr and RSS feeds, which is how I have moved a couple of ancient blogs onto a static blogging setup.

Serving output needs no Python at all

The output/ directory is plain HTML. Copy it to any web server and the Python environment is no longer involved:

rsync -av --delete output/ user@server:/srv/blog/

A Caddy file_server block or nginx serves it with the memory footprint of a static site, which is why a Pelican blog can live on the same 1 GB VPS as five other things. The --delete flag matters: without it, posts you renamed or removed keep being served from stale files in /srv/blog until you notice. Static output also makes the Core Web Vitals conversation short: there is no database and no render step between the request and the file.

The build step is the cost, and it is real

There is no admin UI, no web editor and no publish button. Writing means a text editor and a terminal, and deploying from a phone is awkward. The build also depends on a Python environment that must exist wherever you build, so either build locally and rsync, or run the build in CI on your Git host (Gitea Actions or a Forgejo runner both do this well). Build time is seconds for a few hundred posts; the Go generators are faster still, which only matters at thousands of pages. If you want the editing experience of WordPress with static output, Pelican is the wrong tool and a CMS with a static export mode is closer.

What I'd do

If Python is your language, Pelican with the Markdown extra, the sitemap plugin, a theme you fork and edit, and a Gitea Actions job that builds on push and rsyncs to Caddy. Import WordPress with pelican-import, spend the cleanup hour, and never run PHP for a blog again. If Python is not your language, the Hugo vs Jekyll comparison is where your decision actually lives.

Compare Pelican

31 head-to-head comparisons.

Similar blogging platforms apps