Brief Overview of Pelican

• 10 min read

Recently I switched this website from Django to a static site. This article gives an overview of the core concepts of Pelican, covering areas that are not directly captured in the official docs. This is written primarily to solidify my own understanding and also act as a reference for myself when I need to maintain it after a prolonged gap.

Static site generators

Static site generators work like the app servers that eventually output the HTML code to the client browser, but do this during the build process which the user invokes to assemble the site from its various fragments. Once generated, the resultant HTML, scripts & image files can be uploaded to an HTTP server such as Apache or NGINX.


Pelican broadly divides the site content as belonging to one of the two types:

  • Pages: These are content, types of which are not constantly created over time. Examples include about page, privacy policy page, contact page, etc. These types of content are created once and usually they remain intact except that details inside them are updated when required.
  • Articles: Articles are running content, new types of which are constantly published and are presented to the visitor in a chronological (usually reverse) order. Examples being blog articles, news items, etc.

Site content is typically written in markdown. They can also be written in other popular publishing formats such as reStructuredText or even HTML.

File Metadata

Whatever format is used, special meta information is placed in content that controls how it's rendered into the final HTML. Example for meta information include tags, categories, date, title, description, etc. This doc shows how to place metadata in content files.


The presentation of the content is controlled by themes. Themes are essentially templates (using Jinja) which contain special placeholders into which content is supplanted during the generate process resulting in the final HTML output. These primarily consist of the following:

  • A site index template. This becomes the site's homepage or index.html.
  • A template for rendering the pages
  • A template for rendering articles
  • A few other templates such as one showing list of tags, articles belonging to a specific tag, list of authors, etc.

Some other points:

  • Themes also include the required CSS & JS files as well as any images.
  • Depending on your required site design constraints, you can either design your own theme templates or use one of the many pre-designed themes.
  • What theme file stands for what type of purpose is based on its filename.
  • Since they use Jinja templating system, they use the {% block %}, {{ variable }}, {{ variable | filter }} type of syntact that should be natural to a Django developer.

You can learn more about themes in the official docs here.

Custom theme

The primary target of Pelican seems to be personal sites where authors can publish content such as articles by writing it in markdown and then update the site by running the pelican to generate it. For such a site, the homepage would typically show the latest articles as and when they are published. This is what most of the themes in the theme library seem to do (I haven't explored them all. So I could be wrong here).

If you're using Pelican to generate a company website, then a homepage showing latest blog articles may not be what you want. Many company sites still have a blog, but typically the blog would be hosted in a subdomain (such as or as a subsite under the main site.

To customize the site's homepage, Pelican does provide a special content meta tag that would render that content's HTML output as the site's homepage ( However, rendered content (articles or pages) tend to consist mostly of text and this may not be ideally suited for a company site's homepage, which typically has a drastically different design than the site's inner pages.

So the solution is to create a custom theme with a suitable index.html that reflects the homepage design that you desire. You can still incorporate pelican content elements inside (such as latest blog articles) it, if you wish to do so.


Pelican configuration file,, controls what theme to use and other relevant hints to the site generator. A full documentation of Pelican's settings is here.

Note however that, for publishing the site to the web a different configuration file, is used. This file imports all settings from, but overrides some of them for production configuration (borrowing the term from Angular).

One such configuration that is typically different in development and production configurations is the site's URL. For local dev configuration this will be an empty string and for production this will be the full URL of the domain(SITEURL setting). This matters are the generated hyperlinks are prefixed with this setting's value in the templates and setting its value correctly will ensure that the embedded hyperlinks to navigate between different pages within the site work as expected. Make sure you prefix the URL with the correct scheme. So if your site runs on HTTPS it should be


Pelican supports plugins which extend the feature set of the core system. For instance localization is provided via the plugin i8n_subsites. There's also a plugin to automatically generate sitemap file that you can upload to search engines.

While some plugins are independent packages that can be installed using pip, others require the relevant repository to be cloned locally and its path given to pelican via the pelican configuration file (see below).

For example the sitemap plugin is installed as an independent package via pip install pelican-sitemap command whereas the localization plugin i8n_subsites is installed by replicating the repo locally.

For plugins that require its repository to be locally maintained, a useful convention is to store them under a plugins folder beneath the project's root folder.

The location where plugins are searched for is specified via the PLUGIN_PATHS configuration as shown below. The plugins itself to be applied are specified via the PLUGINS setting.

PLUGIN_PATHS = ["./plugins"]
PLUGINS = ["i18n_subsites", "sitemap"]

Historically plugins are maintained in this repository, but there's a new initiative to maintain the plugins under their own github organization here. Not all plugins from the historical repository has been ported over to the new organization.


I hope this gives a brief overview of Pelican and its core concepts. The documentation is excellent though it falls short of an overview doc like this. Perhaps there are other resources out there that this replicates. But I couldn't find any and hence I decided to write this up.