I moved from the Pelican Python static website generator back to a static website with Jekyll and Github Pages.


Install Ruby

Install RVM as seen here

$ gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
$ \curl -sSL https://get.rvm.io | bash -s stable

If you are on Linux/Gnome. As seen here. Go to the Terminal preferences and find a checkbox that says Run command as a login shell. This must be checked.

Close the terminal and open it again.

$ source ~/.rvm/scripts/rvm
$ type rvm | head -n 1

This should say rvm is a function

Restart the shell and Install Ruby. Stable version on 5/24/20 is 2.7.1

$ rvm install 2.7.1
$ rvm use 2.7.1 --default

Create a gemset for the blog

$ rvm use [email protected] --create

List gemsets with:

$ rvm gemset list

Switch gemsets with:

$ rvm gemset use name-of-gemset

Install Jekyll

Setup Jekyll:

$ gem install bundler jekyll

Go to the root directory where you want to install. Then create a new jekyll blog.

$ jekyll new blog
$ cd blog

This creates the following:


Run the blog:

$ bundle exec jekyll serve

Open http://localhost:4000 and Ctrl+C to stop

Jekyll and Github Pages

Look at Github pages dependency versions

As of 5/24/20:

  • jekyll: 3.8.5 (even though latest stable was 4.0.1)
  • github pages: 204

Modify the Gemfile to use Github pages as shown.

  • Comment this line: gem "jekyll", "~> 4.0.1"
  • Uncomment this line: gem "github-pages", group: :jekyll_plugins


$ bundle update

Output was:

Note: jekyll version regressed from 4.0.1 to 3.8.5

Run bundle:

$ bundle install


Bundle complete! 6 Gemfile dependencies, 85 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

Test again:

$ bundle exec jekyll serve

Troubleshooting dependency errors

When testing the site. For jekyll-3.8.5 it says warning: Using the last argument as keyword parameters is deprecated.

  • Also for pathutil-0.16.2 it says the same.
  • More here
  • And here

Edit the Gemfile and comment this line again gem "github-pages", group: :jekyll_plugins. Then add this one:

gem 'jekyll', github: 'jekyll/jekyll'

If you have plugins update them to this:

group :jekyll_plugins do
    gem 'jekyll-feed', github: 'jekyll/jekyll-feed'
    gem 'jekyll-sitemap', github: 'jekyll/jekyll-sitemap'
    gem 'jekyll-paginate', github: 'jekyll/jekyll-paginate'
    gem 'jekyll-seo-tag', github: 'jekyll/jekyll-seo-tag'
    gem 'jekyll-redirect-from', github: 'jekyll/jekyll-redirect-from'

My Gemfile currently looks like this:

source "https://rubygems.org"

gem 'jekyll', github: 'jekyll/jekyll'

gem "minima", "~> 2.5"

group :jekyll_plugins do
    gem 'jekyll-feed', github: 'jekyll/jekyll-feed'
    gem 'jekyll-sitemap', github: 'jekyll/jekyll-sitemap'
    gem 'jekyll-paginate', github: 'jekyll/jekyll-paginate'
    gem 'jekyll-seo-tag', github: 'jekyll/jekyll-seo-tag'
    gem 'jekyll-redirect-from', github: 'jekyll/jekyll-redirect-from'

Then run bundle install

Using a theme and edit _config.yml

The default theme is minima. The docs have good details on how to set it up.

It has instructions on how to set your _config.yml

Mine looks kinda like this:

title: Name and Title of My Blog
description: >-
  Some awesome description here
baseurl: ""
url: "https://www.mywebsite.com"
twitter_username: mytwitter
github_username:  mygithub
permalink: /:title/

# Build settings
theme: minima
  skin: solarized #not seeing this skin yet

  - about.md

    shortname: mydisqus_shortname

  name: My Name

show_excerpts: true

    twitter: mytwitter
    github: mygithub
    linkedin: mylinkedin_shortname

google_analytics: myGAcode

  - jekyll-feed
  - jekyll-feed
  - jekyll-sitemap
  - jekyll-paginate
  - jekyll-seo-tag
  - jekyll-redirect-from

  - .sass-cache/
  - .jekyll-cache/
  - gemfiles/
  - Gemfile

Updating the default theme ‘minima’

The default theme is installed as a gem and you won’t see the source files in your blog directory. To find the source files run this:

$ bundle info minima

My output was this:

* minima (2.5.1)
Summary: A beautiful, minimal theme for Jekyll.
Homepage: https://github.com/jekyll/minima
Path: /home/tom/.rvm/gems/[email protected]/gems/minima-2.5.1

If you open this path, the README file shows where files are located:

  • The _layouts directory define the markup for your theme.
  • The _includes directory has snippets of code that can be inserted in layouts.
  • The _sass directory define the theme’s styles.
  • The assets directory contains the main.scss.

The main.scss imports sass files from the _sass directory. It gets processed into the theme’s main stylesheet main.css called by _layouts/default.html via _includes/head.html.

To override the default structure and style, create the specific directory at the root of the blog, copy the file to that directory, and then edit the file.

For example:

  • To override the _includes/head.html.
  • Create an _includes directory in the root of your blog.
  • Copy _includes/head.html from minima gem folder to this directory.
  • Edit that file.

Updating the default CSS

  • Go to the gem path.
  • Copy the assets/ folder to your blog root.
  • Edit the /assets/main.scss file.

Using a different theme

I tried a theme that looked Medium

Instead of installing Jekyll as shown above, do the following:

$ git clone https://github.com/wowthemesnet/mundana-theme-jekyll.git blog
$ cd blog
$ bundle
$ bundle exec jekyll serve

I liked it for a while but it had some weird bugs. I spent many hours trying to fix them but then I gave up and switched back to the default minima theme.

Creating an about page

In your root blog create edit the default about and modify it as about.md:

layout: page
title: "About"
permalink: "/about.html"
comments: false

Creating blog posts

These go in the _posts folder. I got a template that I follow for each new blog post:

layout: post
title: "Title in Double Quotes"
author: tom
categories: [A category]
tags: [some tags here]

file: YYYY-MM-DD-title.md (or it won't show up)
title: Don't forget to update this
Add images with: ![Image Name]({{ site.baseurl }}/assets/images/add_image.jpg)
Add local URL with: [Local URL](../local-url)

Creating redirects

Add this to the Gemfile in the plugins block:

gem 'jekyll-redirect-from', github: 'jekyll/jekyll-redirect-from'

Then run bundle install.

As seen in the docs here

Add it to the _config.yml under plugins

- jekyll-redirect-from

My problem was that for my previous website, the blog posts had this format:


This new website removes the .html and a lot of blog posts crawled by google are being sent to a 404 File not found page.

I want to redirect blog_post_name.html to blog_post_name/

In the blog post the header should show something like this:

title: "Blog Post Name"
  - /blog_post_name.html

404 page

More about 404 pages here

You can create a 404.md file if you add this:

layout: page
title: "Not Found"
permalink: "/404.html"
comments: false
  - /index2.html

Use the redirect_from: to redirect bad URLs from Google search results. Or use the same approach for blog posts. You can also try to fix them in your Google Search Console.

Add a Favicon

Based on your theme, it should allow you to add a Favicon on the _config.yml. Otherwise you would need to add it directly to the head.html.

For the minima theme, the docs say that you can add an _includes/custom-head.html to your root folder and add your code for the favicon files. However, this didn’t work for me as shown on 2.5.1 can’t include custom-head.html.

I added the favicon code directly to head.html.

Setup Github

Go to Github:

  • Create a new repo with the format username.github.io

Setup the repo:

$ git init
$ git remote add origin link-to-repo

CNAME, robots.txt

If you have a custom domain, create a CNAME file, add a line with your website, and save it to your local blog root directory:


Create a robots.txt and add this line to the file:

User-agent: *

You can also use Disallow for bad URLs.

User-agent: *
Disallow: /bad.html
Allow: /

Deploy to Github

If you want to cache your credentials

$ git config --global credential.helper 'cache --timeout=3600'

Then deploy:

$ git status
$ git add .
$ git commit -m "Awesome commit message here"
$ git push -u origin master

Change your DNS name server

Setup an account with Cloudflare if you don’t have one. Find the DNS name server

In your DNS provider point it to Cloudflare.

Cloudflare settings

Create these records in Cloudflare:

Type    Name               Content
ALIAS   yoursite.com       youruser.github.io
CNAME   www.yoursite.com   youruser.github.io
TXT     yoursite.com       youruser.github.io

Add A records as seen on Setting up an Apex domain

Add TXT record to verify Google webmaster tools:

  • Add property
  • Add TXT google verification code

Setup these Page rules. As seen here

Cache Level: Cache Everything

Forwarding URL: (Status Code: 301 - Permanent Redirect, URl: https://www.yoursite.com$1)

Always Use HTTPS

In your Overview dashboard set these (if you are on the free plan)

  • Security level: medium
  • SSL: Full
  • Caching level: Standard

Migrating content

Here is where I was challenged.

With the Pelican Python static website generator the files were named as title.md. With Jekyll they need to be in the format YYYY-MM-DD-title.md.

For Pelican the header looks like this:

Title: Powerful things you can do with the Markdown editor"
Date: 2020-02-09 20:00
Category: Jekyll, tutorial
Tags: featured
Slug: powerful-things
Author: Tom Ordonez
Status: published
Summary: A blog post about Markdown editor.

For Jekyll it needs to look like this:

layout: post
title:  "Powerful things you can do with the Markdown editor"
author: tom
categories: [ Jekyll, tutorial ]
image: assets/images/11.jpg
tags: [featured]

How to make this change to about 100 blog posts?

I needed to extract the Date from the header and use it to rename the file. Then extract other content like the Title, Category, and Tags. Then replace this header with the new header.

Also the blog posts used this syntax to insert images in the content {static}/images/ while Jekyll uses:

{ {site.baseurl} }/assets/images/

Read more in Python, Files, and OS Module