Creating a Static Blog/Site with Pelican

I had been contemplating what my first blog post would be about, as i needed to break the ice urgently, but then, i decided, why not show the few people who might or might not know about Static Site Generators how useful such negligible tools can be.

Ever wanted to create a personal site or blog and got discouraged by the amount of expertise needed across development, cloud and database setup or conventional hosting? The good thing is we can create static sites and host them for free on Github with Pelican and Github Pages. There are other static site generators for different languages and technologies, like; Jekyll for Ruby, Hexo for Javascript, but we would be focusing on Pelican for Python.

Just so you know, this whole site is built and hosted for free, using technologies discussed below.

So what exactly is a static site?

Most websites on the internet today comprise of various technologies both complex and feasible and mostly tend to involve a database, a server, CRUD (Create, Read, Update and Delete) operations, asynchronous tasks, et al. These kind of flexible and mutable data dependent sites are what we mostly refer to as Dynamic Sites.

Static sites are less complex in the sense that most of the information on the site does not necessarily need to change frequently over time. Such sites do not have a database attached or need to perform any data intensive operations, they do not need to collect your information, they are mostly to display information.

Lets say we wanted to create a blog, in a Static Site architecture, if a user needs to view a post, the server simply returns the appropriate HTML template mapped to the requested URL and renders it to the user. But in a Dynamic Site architecture, when a user tries to view a blog post, the server (database) would first be queried to return details about the specified blog post and then return the results to the client. They both have their various pros and cons which can be easily understood with a simple Google Search

What are Static Site Generators?

In few words

Static site generators take content written in a particular format, Markdown, reStructuredText and translates it to HTML based on certain rules given in a configuration file.

Some Benefits of Static Site Generators:

  • Cheap Scaling: Pre-rendered static files can stand the onslaught of traffic if your post makes it to the top of hackernews or reddit very cheaply. No queries are being made.
  • Any format: You can use reStructuredText, Markdown etc. to write your posts.
  • Host Anywhere: Static sites can be hosted easily on github pages, Amazon S3 and even dropbox.
  • Own Everything: You have access to all your posts and all your themes. No company in the middle, just you and your content.
  • Control: Static site generators give you a lot of control over pretty much every aspect of your site through templates and plugins, allowing you to quickly add complex functionality not found in popular web blogging platforms.
  • Update Issues: If you are using wordpress, you have to update your software when a new version comes out; otherwise, you have a security risk. However, one can use the same version of a static blog generator indefinitely.

Advantages of Using Pelican:

Pelican is our chosen Static Site Generator and below are some of it's advantages:

  • Plugins: Pelican has a lot of plugins, that allow you to quickly add functionality.
  • Hackable: Extending pelican as well as altering its behaviour is simple.
  • Themes: Pelican has a lot of themes, and you can make your own.
  • Multi-platform: Works well on Windows, OSX and Linux.

Getting Started

There are some basic technologies and concepts you need to know to fully understand how this whole thing works, some of which are;

  • Python, Pip, Virtualenvs
  • Git, Bash

Installing Pelican

Installation is very simple. It is highly advised that you create a Virtual Environment for your python applications, see this post for more.

  1. You must have a full python development setup.
  2. Start your virtual environment and navigate to the folder where your site files would be stored.
  3. Install Pelican which would also install Markdown, blinker, et al.
$ pip install pelican
Collecting pelican
  Using cached pelican-3.7.1-py2.py3-none-any.whl
Collecting markdown
  Downloading Markdown-2.6.9.tar.gz (271kB)
    100% |████████████████████████████████| 276kB 336kB/s 
Collecting blinker (from pelican)
Collecting unidecode (from pelican)
  Downloading Unidecode-0.04.21-py2.py3-none-any.whl (228kB)
    100% |████████████████████████████████| 235kB 305kB/s 
.
.
.
Installing collected packages: blinker, unidecode, pytz, six, feedgenerator, pygments, docutils, MarkupSafe, jinja2, python-dateutil, pelican, markdown
Successfully installed MarkupSafe-1.0 blinker-1.4 docutils-0.14 feedgenerator-1.9 jinja2-2.10 markdown-2.6.9 pelican-3.7.1 pygments-2.2.0 python-dateutil-2.6.1 pytz-2017.3 six-1.11.0 unidecode-0.4.21

After Pelican and all it's dependencies are installed, you can then advance to starting site generation with pelican.

Basic Setup

To kickstart your development process, enter pelican-quickstart in your terminal with your virtual environment enabled.

$ pelican-quickstart
Welcome to pelican-quickstart v3.5.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? [.]
> What will be the title of this web site? Site Title
> Who will be the author of this web site? Captain America
> What will be the default language of this web site? [en]
> Do you want to specify a URL prefix? e.g., http://example.com   (Y/n) n
> Do you want to enable article pagination? (Y/n)
> How many articles per page do you want? [10] 8
> Do you want to generate a Fabfile/Makefile to automate generation and publishing? (Y/n)
> Do you want an auto-reload & simpleHTTP script to assist with theme and site development? (Y/n)
> Do you want to upload your website using FTP? (y/N)
> Do you want to upload your website using SSH? (y/N)
> Do you want to upload your website using Dropbox? (y/N)
> Do you want to upload your website using S3? (y/N)
> Do you want to upload your website using Rackspace Cloud Files? (y/N)
> Do you want to upload your website using GitHub Pages? (y/N)
Done. Your new project is available at /Users/Nosa/Projects/blog

You can simply leave certain fields blank as their default values (Uppercased values between the parentheses) would suffice. You should now have the following folder structure:

.
├── Makefile
├── content/
├── develop_server.sh
├── fabfile.py
├── output/
├── pelicanconf.py
└── publishconf.py

Briefly to explain what each file/folder does/contains:

  1. Makefile: a file that contains configurations used when running commands with make
  2. content: a folder that would contain our pages and articles writing in either Markdown or reStructuredText format. This is the folder Pelican looks into when trying to convert our files to HTML
  3. develop_server.sh: a bash file used by Pelican
  4. fabfile.py: a file used when automating processes through Fabric
  5. output: a folder which would contain the rendered HTML files, this is the folder we are to deploy to our various hosting platforms or to Github Pages.
  6. pelicanconf.py: a file that holds settings and configurations needed by Pelican during conversion.
  7. publishconf.py: a file used by Pelican during publishing

Creating Articles

We would use Markdown to write our first entry, but you can also use reStructuredText. Change your current directory to the content directory and create a new file with the markdown extension (.md)

$ cd content
$ sudo nano first_post.md

Enter the following

Title: My First Post
Date: 2017-11-14 18:32
Category: Test

Thanks to Pelican

The Title, Date and Category are post metadata used to provide reusable information about the article being written, there are various other metadata used for posts like; tags, author, summary, which are sometimes specific to the Theme being used and the corresponding configuration files. Every other text beneath the metadata section is the body of the text.

Start a development server

Now run the command for starting a development server

make devserver

Browse to http://localhost:8000 to see your newly created site.

Using Themes, Plugins and Settings

Pelican settings and choosing a theme/plugin are covered fully in the following articles:

  1. Understanding Pelican Settings
  2. Using Pelican Themes and Plugins

I personally use the atilla theme from the Pelican Themes Repository

Writing complex articles

To fully write meaty articles, you need to know how to implement lists, headings, images, bold and italics, etc in markdown and the following post would provide all you need to get up to speed with Markdown.

This blog post has an awesome script for automating the creation of posts by using command line arguments to specify the Title, then the script automates the inclusion of the various necessary metadata.

Below is a sample script that automates the creation of a post:

We create a python file named create_post.py

import sys
from datetime import datetime

TEMPLATE = """
title: {title}
date: {year}-{month}-{day} {hour}:{minute:02d}
tags:
category:
slug: {slug}
summary:
status: draft
"""


def create_post(title):
    today = datetime.today()
    slug = title.lower().strip().replace(' ', '-')
    file_name = "content/{}_{:0>2}_{:0>2}_{}.md".format(
        today.year, today.month, today.day, slug)
    t = TEMPLATE.strip().format(title=title,
                                year=today.year,
                                month=today.month,
                                day=today.day,
                                hour=today.hour,
                                minute=today.minute,
                                slug=slug)
    with open(file_name, 'w') as w:
        w.write(t)
    print("File created -> " + file_name)

if __name__ == '__main__':
    if len(sys.argv) > 1:
        create_post(sys.argv[1])
    else:
        print "No title given"

The script above requires a title to be passed as an argument when running the file and it then populates certain metadata based on the title and date.

We can then simply create a new file:

$ python create_post.py "My First Pelican Site"
File created -> content/2014_12_13_my-first-pelican-site.md

Remember that the content folder holds the raw files which would then be converted to HTML by Pelican and the output folder contains the converted HTML files.

Hosting your new site freely on Github

GitHub is a Web-based Git version control repository hosting service. It is mostly used for computer code. It offers all of the distributed version control and source code management functionality of Git as well as adding its own features.

In order to get a sitename as http://username.github.io one needs to create a repository on github named username.github.io, set it as public and empty. This is the repository where you would push the content of your output folder. Once your repository has been created, take note of the remote url.

You would also need a repository to hold all the files, both the output folder and the content folder and all files involved, as a back up. Most people prefer using Git Submodule since the output folder is contained in the same parent folder as the content folder, so we would need to have a git repository inside a git repository, not so complicated, but beyond the scope of this tutorial.

So initialize an empty git repository in both the output folder and it's parent folder

$ cd output
$ git init
$ git remote add origin https://github.com/username/output_repo

$ cd ..
$ git init
$ git remote add origin https://github.com/username/full_blog_repo

Then push the content of the output folder to the appropriate repository username.github.io.

$ git add .
$ git commit -m "ain't i awesome"
$ git push

Remember to also add a .gitignore file and add *.pyc and also push the content of the parent folder when you please, this is more of a backup scheme.

If all things go well, you should see your newly created site at http://username.github.io

Custom domains

In order to get your own top level domain like I have with nosahama.com, you simply need to add a CNAME file with your domain in it. The CNAME file must me located inside your output directory and must only have the domain name you intend to use. My CNAME file looks like this:

nosahama.com

The CNAME file must be included when you are pushing to your github repo.

Once this is done, you need to link your domain up with github, follow this post to setup a personal domain with github on namecheap, but the tutorial follows principles applicable to other domain companies.

Not to make this article more verbose than it already is, i've broken down other aspects of Pelican into various other articles:

  1. Understanding Pelican Settings
  2. Using Pelican Themes and Plugins

You can read more about Pelican at their Official Documentation

Show Comments