Upgrading Jekyll 2 to 3 on GitHub Pages

Is your Jekyll site broken on GitHub Pages?

If you didn’t know about the new Jekyll 3 release, you probably got surprised when you opened your website hosted by GitHub and saw that some things were broken (and they weren’t before). The problem is not due to Jekyll upgrade though. The thing is, GitHub Pages environment has changed!

Until January of 2016, the version running on GitHub Pages was Jekyll 2.4.0. On February 1st, they changed it to Jekyll 3.0.2, which provoked a bunch of broken sites. Currently (on 2016-03-30), GH Pages is building with Jekyll 3.0.3. Looks like they will keep upgrading. You can check here which version and dependencies are running on GitHub Pages at the time you read this article.

GitHub recently published another post on their blog explaing themselves a little better and providing the community with some answers.

Bottom line, another wave of broken sites is expected to May 1st, 2016. From this date on, GitHub Pages will not support redcarpet, rdiscount nor redcloth anymore. It means we’ll need to work with kramdown only.

What has changed?

Jekyll 3.x has changed substantially from it’s 2.x version. The main reasons for these changes was decreasing the number of dependencies and avoid Python, they wanted everything running on Ruby only. Take a look at the table below.

Propriety Jekyll 2.x Default Jekyll 3.x Default
Markdown Redcarpet Kramdown
Highlighter Pygments Rouge
Collection collection[0] collection.label
Requirement Python
Gem jekyll-paginate
Gem jekyll-gist
Post Date future: false
Flag --incremental
Flag --profile
Relative permalinks relative_permalinks
Permalinks trailing slash automatic

If you use any of the features listed on the second column of the table, you’ll have to adapt your site.

The changes that mostly affected or will affect the users are regarding Markdown, Highlighter and Collections. For the new flags, they are very welcome!

Let’s take a look one by one on the overview below. We’ll focus on markdown, highlighter and the gems mentioned above. We’ll also give you a brief description on the other changes.

If the changes to adapt your project are substancial and you would like a better alternative, please check the alternative methods at the end of this post.



Moving from redcarpet or rdiscount to kramdown shouldn’t be so painful. Kramdown has a lot of interesting features. For example, you can easily apply in-line classes and IDs to your markdown text and you can add as many html tags you want to markdown files. Here you learn some Markdown Tips & Tricks for Kramdown and here you can read more about Kramdown Syntax.

Now, if you were using RedCloth though, here you will find an article where the author walk you through the process.

Let’s get it done. In your _config.yml file, make sure you have this:

markdown: kramdown
  input: GFM

GFM stands for GitHub Flavored Markdown.

There is something boring that you’ll need to deal with. Perhaps you used to add headings to your markdown files like this:

#My h1 heading

##My h2 heading

Now, with Kramdown, make sure you have a blank space between the # markup and the title itself, otherwise you will most likely face some output errors:

# My h1 heading

## My h2 heading

Code Highlighter

Now GitHub Pages only supports Rouge as code highlighter. If you used pygments before, don’t worry, Rouge is fully compatible with it. So, the only thing to do is changing your _config.yml, making sure it has:

highlighter: rouge

With Rouge, you won’t need Python installed locally to work on your Jekyll site. It is fully written in Ruby. It also provides full backtick support for highlighting your code.

Instead of writing the usual {% highlight %} tag to every code block:

{% highlight %} 
{% endhighlight %}

You can do the same with backticks:


Here you’ll find all languages and lexers supported by Rouge.

And you can also add line numbers:

def foo
  puts 'foo'

with the standard {% highlight %} markup:

{% highlight ruby linenos %}
def foo
  puts 'foo'
{% endhighlight %}

If you want to display line numbers on every code block, you can easily do that by adding this line to your _config.yml:

line_numbers: true

Note that both {% highlight %} and backticks are fully supported by Rouge.

Dropped Dependencies

As we explained before, one of the major requirements for running Jekyll has dropped: Python. This saves us a lot of trouble, and makes Jekyll installation on Windows a lot easier. Also, all the following dependencies have dropped.

  • jekyll-paginate – Jekyll’s pagination solution from days past
  • jekyll-coffeescript – processing of CoffeeScript
  • jekyll-gist – the gist Liquid tag
  • pygments.rb – the Pygments highlighter
  • redcarpet – the Markdown processor
  • toml – an alternative to YAML for configuration files
  • classifier-reborn – for site.related_posts

As they are not required by default anymore, if your site uses any of this gems, you’ll need to add them manually, otherwise your site most likely won’t build or will break. Or even worst, it’s already broken. But don’t worry, all those changes have a workaround.


A nice touch for code blocks is using embed GitHub Gist Snippets:

This can be done with a single <script> tag:

<script src="https://gist.github.com/VirtuaCreative/ef47c25b7f8933dd78fcb0f848464dde.js"></script>

The gem jekyll-gist would allow us to simplify embed GitHub Gist Snippets, with just a simple tag like {% gist <user/id> %}, where <user/id> is your username/gist_id.

For example, the liquid tag below would reproduce the same result as we just did with the <sript> tag:

{% gist VirtuaCreative/ef47c25b7f8933dd78fcb0f848464dde %}

Troubleshooting jekyll-gist

When trying to use jekyll-gist locally, I’ve faced the error shown below.

  Liquid Exception: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed in C:/Users/Me/websites/test/_posts/2016-03-30-code-blocks.markdown jekyll 3.0.3 | Error:  SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

After some research, I’ve noticed that it is a known issue reported at GitHub issue tracker. The bottom line is, jekyll-gist works on GitHub Pages, but (for me, on Win 7) the error persists locally.


Jekyll 3.x also dropped jekyll-paginate, which tons of Jekyll developers use frequently. But you can add it back to your project and use it as before.

Troubleshooting jekyll-paginate

When I first tried to upgrade this blog from Jekyll 2.x to Jekyll 3.x, my posts were not displaying. I reported the error and Parkr (who is a Jekyll core developer) helped me to find out what the issue relied on. The problem was serving Jekyll in the --safe mode (the method recommended by GitHub). So, when I ran bundle exec jekyll serve --safe my posts didn’t displayed within {% for post in paginator.posts %} at all. But, by running bundle exec jekyll serve they were back there, exactly as they should be.

Add the gems back with Bundler

The good news is, any of those gems can be added back to our projects. :smiley:

Actually, the best and safest way to build Jekyll locally is using Bundler. For Jekyll sites hosted by GitHub Pages, the only required gem is github-pages. Bundler is a fantastic dependency manager, when we use it, we don’t need to worry about dependencies anymore.

Serving Jekyll with Bundler

Follow these steps:

- 1. Install Bundler locally gem install bundler

- 2. On a terminal, navigate to your project cd path/to/project

- 3. On your _config.yml, add the gems you want as an array:

  - jekyll-paginate
  - jekyll-gist

- 4. Create a Gemfile (without any extensions) with the following content:

source 'https://rubygems.org'
gem 'github-pages'
gem 'jekyll-paginate'
gem 'jekyll-gist'

- 5. Run bundle install

- 6. Serve Jekyll with Bundler bundle exec jekyll serve --watch

You’re good to go, then! You can add any flag to the last command. E.g. bundle exec jekyll serve --watch --incremental --baseurl "". Once and awhile, run bundle update on your project to make sure all gems are up to date.

Of course, you can add more gems to your Gemfile if you need. For example, on this blog we use jemoji and jekyll-mentions too. Here you’ll find a list of all gems whitelisted by GitHub Pages.


This is just a brief description. Using collections has become a little better in terms of its logic: site.collections is an array of collections, thus:

collection[0] becomes collection.label

collection[1] becomes collection

To know more about it, please read the doc Jekyll - Upgrading from 2 to 3.

Post Date

The future flag allows post authors to give the post a date in the future and to have it excluded from the build until the system time is equal or after the post time. If you want to create posts with future dates, you will need to add the flag --future when serving Jekyll, as in jekyll serve --future. Alternatively, you can enable it on your _config.yml:

future: true

Liquid Profiler

By adding the flag --profile to the build or serve command, Jekyll will analyze your site’s build time, so you can see exactly where things can be sped up, ensuring you spend more time authoring content, and less time waiting for your site to build.


Our builds can also speed up considerably with by adding the flag --incremental. This will only re-build the files that had been changed. It means it won’t build everything again. For example, if we are writing a post, running jekyll serve --incremental will re-build the post page only, not the entire site. Alternatively, you can set incremental: true in your _config.yml.

Jekyll 3.x does not support relative permalinks anymore. If you have on your _config.yml the following line, you’ll need to remove it.

relative_permalinks: true

In Jekyll 2, any URL constructed from the permalink: variable had a trailing slash (/) added to it automatically. Jekyll 3 no longer adds trailing slashes automatically to permalink: URLs.

Basically, instead of, for example:

permalink: /:year-:month-:day-:title

you’ll need to make sure it has a trailing slash at the end, otherwise you might face a lot of 404 errors:

permalink: /:year-:month-:day-:title/

Alternative Methods

You might ask yourself if there is a better way to walk trough this process. The answer is: yes and no! :grin: If you want to do everything by the book, no. If you want a smart workaround, yes. I see three alternatives, described below.

1. Upload the _site folder

Instead of letting GitHub build your site for you, you can upload only the _site folder. By doing this, you will push to your repository the site pre-compiled from your local machine. It’s a quick way out. And there is a plus here: you can use any Jekyll Plugin available (building locally) and upload the static site only.

2. Travis CI

You can use Travis CI to trigger a non-default build for you. But it’s a little complicated if you don’t know anything about it so far. It’s a quick way out too, if you know what you’re doing!

3. GitLab Pages

I really think it’s worth considering to migrate your site to GitLab Pages. GitLab is a git remote repository manager, with extended functionality. You can create a free account at GitLab.com and enjoy its features, including unlimited free private repos.

The thing is, with GitLab Pages you can choose which Jekyll version you want your project to be build with (you can do a lot more than that, actually). E.g. on this project, the Jekyll version building this site is 2.5.3. So, despite of any Jekyll upgrades, we wouldn’t be obligated to change anything at all on our sites! The choice of upgrading or not, would be up to ourselves only.

If your project on GitHub already has a CNAME pointing to your custom domain, you’d need just to import it to GitLab and add a .gitlab-ci.yml configuration file like this. Then you just specify the Jekyll version on your Gemfile and that’s it! No stress, no redirects, no problems! :+1:

Setting up your site on GitLab Pages will be the subject of our very next post. We’ll try to bring you video tutorials to make it easier to follow through.

We’ll migrate this blog to GitLab Pages soon! :smiley:


Please, let us know if you have any questions by commenting below. If you want to ask questions to the Jekyll Team directly, they have a forum for that, called Jekyll Talk.


Did we miss something? Spotted an error? Please add a new issue on GitHub to let us know! Any contribution is more than welcome!

Next Post

On our next post we will bring you an alternative for GitHub Pages, GitLab Pages. It’s a fantastic alternative to GitHub itself, actually. They both have pros and cons, but GitLab is really worth trying. We’ll discuss it soon! So, stay tunned for our updates!! Follow us on Twitter and/or subscribe to our YouTube Channel!


Last update: 04/10/2016 - 18:16h.