Configuring Jekyll for User and Project GitHub Pages
15 Aug 2015 | GitHub Pages, JekyllYou’ve chosen a Jekyll theme and set it up for your GitHub user page. It looks great and works well.
That theme is your favorite and you want to reuse the tweaks you added, so you apply it to your GitHub project pages, except there’s a small problem: you’re seeing a double-slash in the URL after the repository name, like http://you.github.io/your-project//a-post.html.
Or maybe there’s a much larger problem: many of the in-site links are broken and yield a frustrating and confusing 404.
Jekyll was supposed to be fast and simple. What’s going on? How can you fix it?
Usually, the defect comes from one or both of these:
- Your settings – incorrect data in
_config.yml
- The theme – incorrect usage of Jekyll variables and Liquid tags
Once you tidy your settings and theme, your user and project pages will have normalized URLs and working links. Even better: they will Just Work™ if you use Jekyll locally to preview your sites.
Configuring your site correctly
There is only one rule to follow for _config.yml
:
Rule 0a – For a User site, baseurl
must be empty
Good | baseurl: |
Bad | baseurl: / |
Rule 0b – For a Project site, baseurl
must begin with a slash
Good | baseurl: /your-repository |
Bad | baseurl: your-repository |
Bad | baseurl: your-repository/ |
Using Jekyll and Liquid correctly
There are thee rules to follow:
Rule 1 – Always concatenate Jekyll and Liquid tags
Good | href="{{ site.baseurl }}{{ post.url }}" |
Bad | href="{{ site.baseurl }}/{{ post.url }}" |
This removes the double-slash from your site’s URLs.
Rule 2 – (Almost) Always start links with {{ site.baseurl }}
Good | href="{{ site.baseurl }}{{ post.url }}" |
Bad | href="{{ post.url }}" |
This fixes almost all of the in-site links. The next rule covers the remainder.
Exception: Start hyperlinks with {{ site.url }}{{ site.baseurl }}
in feed pages, like atom.xml.
Otherwise, feed readers and other aggregators, which rely on absolute URLs, won’t be able to send subscribers to your pages.
Rule 3 – Always use a trailing slash after {{ site.baseurl }}
Good | href="{{ site.baseurl }}/" title="Home" |
Bad | href="{{ site.baseurl }}" title="Home" |
Good | href="{{ site.baseurl }}/public/favicon.ico" |
Bad | href="{{ site.baseurl }}public/favicon.ico" |
This fixes links to resources.
Checking your site for link correctness
A few simple grep
searches from your repository’s root will show you what you need to fix, and where.
Find links that don’t concatenate Jekyll tags
grep -r href=\" . | grep 'href=\"{{ *site\.b*a*s*e*url *}}/{' | grep -vE _posts\|_site
If there are any hits, apply Rule 1 to your theme.
Find links that don’t use a Jekyll tag in their href
grep -r href=\" . | grep -v 'href=\"{{ *site\.b*a*s*e*url *}}' | grep -vE _posts\|_site
The only hits should be to external resources and pages. If there are any that point into your site, you need to apply Rule 2 to your theme.
Find links that don’t use a trailing slash after {{ site.baseurl }}
grep -r href=\" . | grep 'href=\"{{ *site\.baseurl *}}[^/{]' | grep -vE _posts\|_site
If there are any hits, apply Rule 3 to your theme.
Why are these the rules to follow?
Two reasons:
- It’s the way HTTP URLs work
- It’s the way Jekyll works
HTTP URL structure
HTTP supports two kinds of links: absolute and relative. Absolute links have the full and complete URL, while relative links have a variety of flavors. The one that matters for us is the one that starts with a leading slash. When a browser is on a web page, it can assume that the target of a link with a leading slash is on the same host.
For example, assume a page at http://host.com/folder/page.html
wants to link to http://host.com/folder/other.html
, then these are equivalent href links:
<a href="http://host.com/folder/other.html">Go</a>
<a href="/folder/other.html">Go</a>
The browser will navigate to the same page when you click on either link.
Jekyll’s rendering behavior
Jekyll adopted this style of in-site linking, and so it uses leading-slash relative links whenever it populates variables like page.url
(for more information, see my previous post about exploring Jekyll variables). So, when providing your own URL data, like site.baseurl
, it’s important that you use the same pattern. See Jekyll’s documentation for GitHub Pages if you want a second (and identical) opinion.
While there is much more behind HTTP uniform resource locators than the simplification below, here are the basic building blocks, with a slightly different delineation so that they match Jekyll variable names.
User Page
http://you.github.io/a-post.html
- site.url
- page.url
Violation | Result |
---|---|
Rule 0 bare slash |
http://you.github.io//a-post.html |
Rule 1 slash between tags |
http://you.github.io//a-post.html |
Rule 2 missing site.baseurl |
href="/a-post.html" (!) |
Rule 3 no slash after tag |
href="" title="Home" (x) |
Rule 3 no slash after tag |
href="/public/favicon.ico" (!) |
Notes:
- ! – This result is still correct, but only for a User page. This is a false positive and many theme authors incorrectly assume that this “correct” result is also correct for Project pages.
- x – This is an abnormal relative URL, and browsers will navigate to the current page.
Project Page
http://you.github.io/your-project/a-post.html
- site.url
- site.baseurl
- page.url
Violation | Result |
---|---|
Rule 0 no leading-slash |
http://you.github.ioyour-project/a-post.html (404) |
Rule 0 trailing-slash |
http://you.github.ioyour-project//a-post.html (404) |
Rule 1 slash between tags |
http://you.github.io/your-project//a-post.html |
Rule 2 missing site.baseurl |
href="/a-post.html" (404) |
Rule 3 no slash after tag |
href="/your-project" title="Home" (404) |
Rule 3 no slash after tag |
href="/your-projectpublic/favicon.ico" (404) |