Hyde Press

Simple • Static • Blog-aware

Jekyll Documentation (Book Edition)

by Tom Preston-Werner, Nick Quaranto, Parker Moore, et al

Transform your plain text into static sites and blogs



Note: The book edition is still an early release and a work-in-progess.

This is the (official) documentation for the Jekyll static site builder / generator reformatted in a single-page book edition.

See the source repo for how the book gets auto-built with "plain" Jekyll - of course - and hosted on GitHub Pages.

Questions? Comments? Send them to the Jekyll Talk forum post titled Jekyll Docu Reformatted as a Single-Page in Black 'n' White (Book Version) - Why? Why Not?.



Thanks to all Jekyll contributors for making it all possible.

Part 1 - Getting Started

Chapter 1.1 - Welcome


This site aims to be a comprehensive guide to Jekyll. We’ll cover topics such as getting your site up and running, creating and managing your content, customizing the way your site works and looks, deploying to various environments, and give you some advice on participating in the future development of Jekyll itself.

So what is Jekyll, exactly?

Jekyll is a simple, blog-aware, static site generator. It takes a template directory containing raw text files in various formats, runs it through a converter (like Markdown) and our Liquid renderer, and spits out a complete, ready-to-publish static website suitable for serving with your favorite web server. Jekyll also happens to be the engine behind GitHub Pages, which means you can use Jekyll to host your project’s page, blog, or website from GitHub’s servers for free.

Helpful Hints

Throughout this guide there are a number of small-but-handy pieces of information that can make using Jekyll easier, more interesting, and less hazardous. Here’s what to look out for.

ProTips™ help you get more from Jekyll

These are tips and tricks that will help you be a Jekyll wizard!

Notes are handy pieces of information

These are for the extra tidbits sometimes necessary to understand Jekyll.

Warnings help you not blow things up

Be aware of these messages if you wish to avoid certain death.

You'll see this by a feature that hasn't been released

Some pieces of this website are for future versions of Jekyll that are not yet released.

If you come across anything along the way that we haven’t covered, or if you know of a tip you think others would find handy, please file an issue and we’ll see about including it in this guide.

Chapter 1.2 - Quick-start guide

For the impatient, here’s how to get a boilerplate Jekyll site up and running.

~ $ gem install jekyll
~ $ jekyll new myblog
~ $ cd myblog
~/myblog $ jekyll serve
# => Now browse to http://localhost:4000

If you wish to install jekyll into an existing directory, you can do so by running jekyll new . from within the directory instead of creating a new one. If the existing directory isn’t empty, you’ll also have to pass the --force option like so jekyll new . --force.

That’s nothing, though. The real magic happens when you start creating blog posts, using the front matter to control templates and layouts, and taking advantage of all the awesome configuration options Jekyll makes available.

If you’re running into problems, ensure you have all the requirements installed.

Chapter 1.3 - Basic Usage

The Jekyll gem makes a jekyll executable available to you in your Terminal window. You can use this command in a number of ways:

$ jekyll build
# => The current folder will be generated into ./_site

$ jekyll build --destination <destination>
# => The current folder will be generated into <destination>

$ jekyll build --source <source> --destination <destination>
# => The <source> folder will be generated into <destination>

$ jekyll build --watch
# => The current folder will be generated into ./_site,
#    watched for changes, and regenerated automatically.
Changes to _config.yml are not included during automatic regeneration.

The _config.yml master configuration file contains global configurations and variable definitions that are read once at execution time. Changes made to _config.yml during automatic regeneration are not loaded until the next execution.

Note Data Files are included and reloaded during automatic regeneration.

Destination folders are cleaned on site builds

The contents of <destination> are automatically cleaned, by default, when the site is built. Files or folders that are not created by your site will be removed. Files and folders you wish to retain in <destination> may be specified within the <keep_files> configuration directive.

Do not use an important location for <destination>; instead, use it as a staging area and copy files from there to your web server.

Jekyll also comes with a built-in development server that will allow you to preview what the generated site will look like in your browser locally.

$ jekyll serve
# => A development server will run at http://localhost:4000/
# Auto-regeneration: enabled. Use `--no-watch` to disable.

$ jekyll serve --detach
# => Same as `jekyll serve` but will detach from the current terminal.
#    If you need to kill the server, you can `kill -9 1234` where "1234" is the PID.
#    If you cannot find the PID, then do, `ps aux | grep jekyll` and kill the instance. [Read more](http://unixhelp.ed.ac.uk/shell/jobz5.html).
Be aware of default behavior

As of version 2.4, the serve command will watch for changes automatically. To disable this, you can use jekyll serve --no-watch, which preserves the old behavior.

$ jekyll serve --no-watch
# => Same as `jekyll serve` but will not watch for changes.

These are just a few of the available configuration options. Many configuration options can either be specified as flags on the command line, or alternatively (and more commonly) they can be specified in a _config.yml file at the root of the source directory. Jekyll will automatically use the options from this file when run. For example, if you place the following lines in your _config.yml file:

source:      _source
destination: _deploy

Then the following two commands will be equivalent:

$ jekyll build
$ jekyll build --source _source --destination _deploy

For more about the possible configuration options, see the configuration page.

If you’re interested in browsing these docs on-the-go, install the jekyll-docs gem and run jekyll docs in your terminal.

Chapter 1.4 - Directory structure

Jekyll is, at its core, a text transformation engine. The concept behind the system is this: you give it text written in your favorite markup language, be that Markdown, Textile, or just plain HTML, and it churns that through a layout or series of layout files. Throughout that process you can tweak how you want the site URLs to look, what data gets displayed in the layout, and more. This is all done through editing text files, and the static web site is the final product.

A basic Jekyll site usually looks something like this:

├── _config.yml
├── _drafts
|   ├── begin-with-the-crazy-ideas.textile
|   └── on-simplicity-in-technology.markdown
├── _includes
|   ├── footer.html
|   └── header.html
├── _layouts
|   ├── default.html
|   └── post.html
├── _posts
|   ├── 2007-10-29-why-every-programmer-should-play-nethack.textile
|   └── 2009-04-26-barcamp-boston-4-roundup.textile
├── _data
|   └── members.yml
├── _site
├── .jekyll-metadata
└── index.html

An overview of what each of these does:

File / Directory Description


Stores configuration data. Many of these options can be specified from the command line executable but it’s easier to specify them here so you don’t have to remember them.


Drafts are unpublished posts. The format of these files is without a date: title.MARKUP. Learn how to work with drafts.


These are the partials that can be mixed and matched by your layouts and posts to facilitate reuse. The liquid tag {% include file.ext %} can be used to include the partial in _includes/file.ext.


These are the templates that wrap posts. Layouts are chosen on a post-by-post basis in the YAML Front Matter, which is described in the next section. The liquid tag {{ content }} is used to inject content into the web page.


Your dynamic content, so to speak. The naming convention of these files is important, and must follow the format: YEAR-MONTH-DAY-title.MARKUP. The permalinks can be customized for each post, but the date and markup language are determined solely by the file name.


Well-formatted site data should be placed here. The jekyll engine will autoload all YAML files in this directory (using either the .yml, .yaml, .json or .csv formats and extensions) and they will be accessible via `site.data`. If there's a file members.yml under the directory, then you can access contents of the file through site.data.members.


This is where the generated site will be placed (by default) once Jekyll is done transforming it. It’s probably a good idea to add this to your .gitignore file.


This helps Jekyll keep track of which files have not been modified since the site was last built, and which files will need to be regenerated on the next build. This file will not be included in the generated site. It’s probably a good idea to add this to your .gitignore file.

index.html and other HTML, Markdown, Textile files

Provided that the file has a YAML Front Matter section, it will be transformed by Jekyll. The same will happen for any .html, .markdown, .md, or .textile file in your site’s root directory or directories not listed above.

Other Files/Folders

Every other directory and file except for those listed above—such as css and images folders, favicon.ico files, and so forth—will be copied verbatim to the generated site. There are plenty of sites already using Jekyll if you’re curious to see how they’re laid out.

Chapter 1.5 - Configuration


Jekyll allows you to concoct your sites in any way you can dream up, and it’s thanks to the powerful and flexible configuration options that this is possible. These options can either be specified in a _config.yml file placed in your site’s root directory, or can be specified as flags for the jekyll executable in the terminal.

Configuration Settings

Global Configuration

The table below lists the available settings for Jekyll, and the various options (specified in the configuration file) and flags (specified on the command-line) that control them.

Setting Options and Flags

Site Source

Change the directory where Jekyll will read files

source: DIR

-s, --source DIR

Site Destination

Change the directory where Jekyll will write files

destination: DIR

-d, --destination DIR


Disable custom plugins, and ignore symbolic links.

safe: BOOL



Exclude directories and/or files from the conversion. These exclusions are relative to the site's source directory and cannot be outside the source directory.

exclude: [DIR, FILE, ...]


Force inclusion of directories and/or files in the conversion. .htaccess is a good example since dotfiles are excluded by default.

include: [DIR, FILE, ...]

Keep files

When clobbering the site destination, keep the selected files. Useful for files that are not generated by jekyll; e.g. files or assets that are generated by your build tool. The paths are relative to the destination.

keep_files: [DIR, FILE, ...]

Time Zone

Set the time zone for site generation. This sets the TZ environment variable, which Ruby uses to handle time and date creation and manipulation. Any entry from the IANA Time Zone Database is valid, e.g. America/New_York. A list of all available values can be found here. The default is the local time zone, as set by your operating system.

timezone: TIMEZONE


Set the encoding of files by name. Only available for Ruby 1.9 or later). The default value is utf-8 starting in 2.0.0, and nil before 2.0.0, which will yield the Ruby default of ASCII-8BIT. Available encodings can be shown by the command ruby -e 'puts Encoding::list.join("\n")'.

encoding: ENCODING


Set defaults for YAML Front Matter variables.

see below

Destination folders are cleaned on site builds

The contents of <destination> are automatically cleaned, by default, when the site is built. Files or folders that are not created by your site will be removed. Some files could be retained by specifying them within the <keep_files> configuration directive.

Do not use an important location for <destination>; instead, use it as a staging area and copy files from there to your web server.

Build Command Options

Setting Options and Flags


Enable auto-regeneration of the site when files are modified.

-w, --[no-]watch


Specify config files instead of using _config.yml automatically. Settings in later files override settings in earlier files.

--config FILE1[,FILE2,...]


Process and render draft posts.

show_drafts: BOOL



Use a specific environment value in the build.



Publish posts with a future date.

future: BOOL



Produce an index for related posts.

lsi: BOOL


Limit Posts

Limit the number of posts to parse and publish.

limit_posts: NUM

--limit_posts NUM

Force polling

Force watch to use polling.


Verbose output

Print verbose output.

-V, --verbose

Silence Output

Silence the normal output from Jekyll during a build

-q, --quiet

Incremental build

Enable the experimental incremental build feature. Incremental build only re-builds posts and pages that have changed, resulting in significant performance improvements for large sites, but may also break site generation in certain cases.

incremental: BOOL

-I, --incremental

Serve Command Options

In addition to the options below, the serve sub-command can accept any of the options for the build sub-command, which are then applied to the site build which occurs right before your site is served.

Setting Options and Flags

Local Server Port

Listen on the given port.

port: PORT

--port PORT

Local Server Hostname

Listen at the given hostname.



Base URL

Serve the website from the given base URL

baseurl: URL

--baseurl URL


Detach the server from the terminal

detach: BOOL

-B, --detach

Skips the initial site build.

Skips the initial site build which occurs before the server is started.


X.509 (SSL) Private Key

SSL Private Key.


X.509 (SSL) Certificate

SSL Public certificate.


Do not use tabs in configuration files

This will either lead to parsing errors, or Jekyll will revert to the default settings. Use spaces instead.

Custom WEBRick Headers

You can provide custom headers for your site by adding them to _config.yml

# File: _config.yml
    My-Header: My-Value
    My-Other-Header: My-Other-Value


We only provide one default and that’s a Content-Type header that disables caching in development so that you don’t have to fight with Chrome’s aggressive caching when you are in development mode.

Specifying a Jekyll environment at build time

In the build (or serve) arguments, you can specify a Jekyll environment and value. The build will then apply this value in any conditional statements in your content.

For example, suppose you set this conditional statement in your code:

{% if jekyll.environment == "production" %}
   {% include disqus.html %}
{% endif %}

When you build your Jekyll site, the content inside the if statement won’t be run unless you also specify a production environment in the build command, like this:

JEKYLL_ENV=production jekyll build

Specifying an environment value allows you to make certain content available only within specific environments.

The default value for JEKYLL_ENV is development. Therefore if you omit JEKYLL_ENV from the build arguments, the default value will be JEKYLL_ENV=development. Any content inside {% if jekyll.environment == "development" %} tags will automatically appear in the build.

Your environment values can be anything you want (not just development or production). Some elements you might want to hide in development environments include Disqus comment forms or Google Analytics. Conversely, you might want to expose an “Edit me in GitHub” button in a development environment but not include it in production environments.

By specifying the option in the build command, you avoid having to change values in your configuration files when moving from one environment to another.

Front Matter defaults

Using YAML Front Matter is one way that you can specify configuration in the pages and posts for your site. Setting things like a default layout, or customizing the title, or specifying a more precise date/time for the post can all be added to your page or post front matter.

Often times, you will find that you are repeating a lot of configuration options. Setting the same layout in each file, adding the same category - or categories - to a post, etc. You can even add custom variables like author names, which might be the same for the majority of posts on your blog.

Instead of repeating this configuration each time you create a new post or page, Jekyll provides a way to set these defaults in the site configuration. To do this, you can specify site-wide defaults using the defaults key in the _config.yml file in your projects root directory.

The defaults key holds an array of scope/values pairs that define what defaults should be set for a particular file path, and optionally, a file type in that path.

Let’s say that you want to add a default layout to all pages and posts in your site. You would add this to your _config.yml file:

      path: "" # an empty string here means all files in the project
      layout: "default"

Here, we are scoping the values to any file that exists in the scopes path. Since the path is set as an empty string, it will apply to all files in your project. You probably don’t want to set a layout on every file in your project - like css files, for example - so you can also specify a type value under the scope key.

      path: "" # an empty string here means all files in the project
      type: "posts" # previously `post` in Jekyll 2.2.
      layout: "default"

Now, this will only set the layout for files where the type is posts. The different types that are available to you are pages, posts, drafts or any collection in your site. While type is optional, you must specify a value for path when creating a scope/values pair.

As mentioned earlier, you can set multiple scope/values pairs for defaults.

      path: ""
      type: "posts"
      layout: "my-site"
      path: "projects"
      type: "pages" # previously `page` in Jekyll 2.2.
      layout: "project" # overrides previous default layout
      author: "Mr. Hyde"

With these defaults, all posts would use the my-site layout. Any html files that exist in the projects/ folder will use the project layout, if it exists. Those files will also have the page.author liquid variable set to Mr. Hyde as well as have the category for the page set to project.

  - my_collection:
      output: true

      path: ""
      type: "my_collection" # a collection in your site, in plural form
      layout: "default"

In this example the layout is set to default inside the collection with the name my_collection.


Jekyll will apply all of the configuration settings you specify in the defaults section of your _config.yml file. However, you can choose to override settings from other scope/values pair by specifying a more specific path for the scope.

You can see that in the second to last example above. First, we set the default layout to my-site. Then, using a more specific path, we set the default layout for files in the projects/ path to project. This can be done with any value that you would set in the page or post front matter.

Finally, if you set defaults in the site configuration by adding a defaults section to your _config.yml file, you can override those settings in a post or page file. All you need to do is specify the settings in the post or page front matter. For example:

# In _config.yml
      path: "projects"
      type: "pages"
      layout: "project"
      author: "Mr. Hyde"
      category: "project"
# In projects/foo_project.md
author: "John Smith"
layout: "foobar"
The post text goes here...

The projects/foo_project.md would have the layout set to foobar instead of project and the author set to John Smith instead of Mr. Hyde when the site is built.

Default Configuration

Jekyll runs with the following configuration options by default. Alternative settings for these options can be explicitly specified in the configuration file or on the command-line.

There are two unsupported kramdown options

Please note that both remove_block_html_tags and remove_span_html_tags are currently unsupported in Jekyll due to the fact that they are not included within the kramdown HTML converter.

# Where things are
source:       .
destination:  ./_site
plugins_dir:  ./_plugins
layouts_dir:  ./_layouts
data_dir:     ./_data
includes_dir: ./_includes
collections:  null

# Handling Reading
safe:         false
include:      [".htaccess"]
exclude:      []
keep_files:   [".git", ".svn"]
encoding:     "utf-8"
markdown_ext: "markdown,mkdown,mkdn,mkd,md"

# Filtering Content
show_drafts: null
limit_posts: 0
future:      false
unpublished: false

# Plugins
whitelist: []
gems:      []

# Conversion
markdown:    kramdown
highlighter: rouge
lsi:         false
excerpt_separator: "\n\n"
incremental: false

# Serving
detach:  false
port:    4000
baseurl: "" # does not include hostname

# Outputting
permalink:     date
paginate_path: /page:num
timezone:      null

quiet:    false
defaults: []

# Markdown Processors
  extensions: []

  extensions: []

  auto_ids:       true
  footnote_nr:    1
  entity_output:  as_char
  toc_levels:     1..6
  smart_quotes:   lsquo,rsquo,ldquo,rdquo
  enable_coderay: false

    coderay_wrap:              div
    coderay_line_numbers:      inline
    coderay_line_number_start: 1
    coderay_tab_width:         4
    coderay_bold_every:        10
    coderay_css:               style

Markdown Options

The various Markdown renderers supported by Jekyll sometimes have extra options available.


Redcarpet can be configured by providing an extensions sub-setting, whose value should be an array of strings. Each string should be the name of one of the Redcarpet::Markdown class’s extensions; if present in the array, it will set the corresponding extension to true.

Jekyll handles two special Redcarpet extensions:

Note that you can also specify a language for highlighting after the first delimiter:

    # ...ruby code

With both fenced code blocks and highlighter enabled, this will statically highlight the code; without any syntax highlighter, it will add a class="LANGUAGE" attribute to the <code> element, which can be used as a hint by various JavaScript code highlighting libraries.

All other extensions retain their usual names from Redcarpet, and no renderer options aside from smart can be specified in Jekyll. A list of available extensions can be found in the Redcarpet README file. Make sure you’re looking at the README for the right version of Redcarpet: Jekyll currently uses v3.2.x. The most commonly used extensions are:


In addition to the defaults mentioned above, you can also turn on recognition of GitHub Flavored Markdown by passing an input option with a value of “GFM”.

For example, in your _config.yml:

  input: GFM

Incremental Regeneration

Incremental regeneration is still an experimental feature

While incremental regeneration will work for the most common cases, it will not work correctly in every scenario. Please be extremely cautious when using the feature, and report any problems not listed below by opening an issue on GitHub.

Incremental regeneration helps shorten build times by only generating documents and pages that were updated since the previous build. It does this by keeping track of both file modification times and inter-document dependencies in the .jekyll-metadata file.

Under the current implementation, incremental regeneration will only generate a document or page if either it, or one of its dependencies, is modified. Currently, the only types of dependencies tracked are includes (using the {% include %} tag) and layouts. This means that plain references to other documents (for example, the common case of iterating over site.posts in a post listings page) will not be detected as a dependency.

To remedy some of these shortfalls, putting regenerate: true in the front-matter of a document will force Jekyll to regenerate it regardless of whether it has been modified. Note that this will generate the specified document only; references to other documents’ contents will not work since they won’t be re-rendered.

Incremental regeneration can be enabled via the --incremental flag (-I for short) from the command-line or by setting incremental: true in your configuration file.

Part 2 - Your Content

Chapter 2.1 - Front Matter

The front matter is where Jekyll starts to get really cool. Any file that contains a YAML front matter block will be processed by Jekyll as a special file. The front matter must be the first thing in the file and must take the form of valid YAML set between triple-dashed lines. Here is a basic example:

layout: post
title: Blogging Like a Hacker

Between these triple-dashed lines, you can set predefined variables (see below for a reference) or even create custom ones of your own. These variables will then be available to you to access using Liquid tags both further down in the file and also in any layouts or includes that the page or post in question relies on.

UTF-8 Character Encoding Warning

If you use UTF-8 encoding, make sure that no BOM header characters exist in your files or very, very bad things will happen to Jekyll. This is especially relevant if you’re running Jekyll on Windows.

ProTip™: Front Matter Variables Are Optional

If you want to use Liquid tags and variables but don’t need anything in your front matter, just leave it empty! The set of triple-dashed lines with nothing in between will still get Jekyll to process your file. (This is useful for things like CSS and RSS feeds!)

Predefined Global Variables

There are a number of predefined global variables that you can set in the front matter of a page or post.

Variable Description


If set, this specifies the layout file to use. Use the layout file name without the file extension. Layout files must be placed in the _layouts directory.


If you need your processed blog post URLs to be something other than the site-wide style (default /year/month/day/title.html), then you can set this variable and it will be used as the final URL.


Set to false if you don’t want a specific post to show up when the site is generated.



Instead of placing posts inside of folders, you can specify one or more categories that the post belongs to. When the site is generated the post will act as though it had been set with these categories normally. Categories (plural key) can be specified as a YAML list or a comma-separated string.


Similar to categories, one or multiple tags can be added to a post. Also like categories, tags can be specified as a YAML list or a comma-separated string.

Custom Variables

Any variables in the front matter that are not predefined are mixed into the data that is sent to the Liquid templating engine during the conversion. For instance, if you set a title, you can use that in your layout to set the page title:

    <title>{{ page.title }}</title>

Predefined Variables for Posts

These are available out-of-the-box to be used in the front matter for a post.

Variable Description


A date here overrides the date from the name of the post. This can be used to ensure correct sorting of posts. A date is specified in the format YYYY-MM-DD HH:MM:SS +/-TTTT; hours, minutes, seconds, and timezone offset are optional.

ProTip™: Don't repeat yourself

If you don't want to repeat your frequently used front matter variables over and over, just define defaults for them and only override them where necessary (or not at all). This works both for predefined and custom variables.

Chapter 2.2 - Writing posts

One of Jekyll’s best aspects is that it is “blog aware”. What does this mean, exactly? Well, simply put, it means that blogging is baked into Jekyll’s functionality. If you write articles and publish them online, this means that you can publish and maintain a blog simply by managing a folder of text-files on your computer. Compared to the hassle of configuring and maintaining databases and web-based CMS systems, this will be a welcome change!

The Posts Folder

As explained on the directory structure page, the _posts folder is where your blog posts will live. These files are generally Markdown or HTML, but can be other formats with the proper converter installed. All posts must have YAML Front Matter, and they will be converted from their source format into an HTML page that is part of your static site.

Creating Post Files

To create a new post, all you need to do is create a new file in the _posts directory. How you name files in this folder is important. Jekyll requires blog post files to be named according to the following format:


Where YEAR is a four-digit number, MONTH and DAY are both two-digit numbers, and MARKUP is the file extension representing the format used in the file. For example, the following are examples of valid post filenames:

ProTip™: Link to other posts

Use the post_url tag to link to other posts without having to worry about the URL's breaking when the site permalink style changes.

Content Formats

All blog post files must begin with YAML Front Matter. After that, it’s simply a matter of deciding which format you prefer. Jekyll supports Markdown out of the box, and has myriad extensions for other formats as well, including the popular Textile format. These formats each have their own way of marking up different types of content within a post, so you should familiarize yourself with these formats and decide which one best suits your needs.

Be aware of character sets

Content processors can modify certain characters to make them look nicer. For example, the smart extension in Redcarpet converts standard, ASCII quotation characters to curly, Unicode ones. In order for the browser to display those characters properly, define the charset meta value by including <meta charset="utf-8"> in the <head> of your layout.

Including images and resources

Chances are, at some point, you’ll want to include images, downloads, or other digital assets along with your text content. While the syntax for linking to these resources differs between Markdown and Textile, the problem of working out where to store these files in your site is something everyone will face.

Because of Jekyll’s flexibility, there are many solutions to how to do this. One common solution is to create a folder in the root of the project directory called something like assets or downloads, into which any images, downloads or other resources are placed. Then, from within any post, they can be linked to using the site’s root as the path for the asset to include. Again, this will depend on the way your site’s (sub)domain and path are configured, but here are some examples (in Markdown) of how you could do this using the site.url variable in a post.

Including an image asset in a post:

... which is shown in the screenshot below:
![My helpful screenshot]({{ site.url }}/assets/screenshot.jpg)

Linking to a PDF for readers to download:

... you can [get the PDF]({{ site.url }}/assets/mydoc.pdf) directly.
ProTip™: Link using just the site root URL

You can skip the {{ site.url }} variable if you know your site will only ever be displayed at the root URL of your domain. In this case you can reference assets directly with just /path/file.jpg.

Displaying an index of posts

It’s all well and good to have posts in a folder, but a blog is no use unless you have a list of posts somewhere. Creating an index of posts on another page (or in a template) is easy, thanks to the Liquid template language and its tags. Here’s a basic example of how to create a list of links to your blog posts:

  {% for post in site.posts %}
      <a href="{{ post.url }}">{{ post.title }}</a>
  {% endfor %}

Of course, you have full control over how (and where) you display your posts, and how you structure your site. You should read more about how templates work with Jekyll if you want to know more.

Note that the post variable only exists inside the for loop above. If you wish to access the currently-rendering page/posts’s variables (the variables of the post/page that has the for loop in it), use the page variable instead.

Post excerpts

Each post automatically takes the first block of text, from the beginning of the content to the first occurrence of excerpt_separator, and sets it as the post.excerpt. Take the above example of an index of posts. Perhaps you want to include a little hint about the post’s content by adding the first paragraph of each of your posts:

  {% for post in site.posts %}
      <a href="{{ post.url }}">{{ post.title }}</a>
      {{ post.excerpt }}
  {% endfor %}

Because Jekyll grabs the first paragraph you will not need to wrap the excerpt in p tags, which is already done for you. These tags can be removed with the following if you’d prefer:

{{ post.excerpt | remove: '<p>' | remove: '</p>' }}

If you don’t like the automatically-generated post excerpt, it can be explicitly overridden by adding an excerpt value to your post’s YAML Front Matter. Alternatively, you can choose to define a custom excerpt_separator in the post’s YAML front matter:

excerpt_separator: <!--more-->


You can also set the excerpt_separator globally in your _config.yml configuration file.

Completely disable excerpts by setting your excerpt_separator to "".

Also, as with any output generated by Liquid tags, you can pass the | strip_html filter to remove any html tags in the output. This is particularly helpful if you wish to output a post excerpt as a meta="description" tag within the post head, or anywhere else having html tags along with the content is not desirable.

Highlighting code snippets

Jekyll also has built-in support for syntax highlighting of code snippets using either Pygments or Rouge, and including a code snippet in any post is easy. Just use the dedicated Liquid tag as follows:

{% highlight ruby %}
def show
  @widget = Widget(params[:id])
  respond_to do |format|
    format.html # show.html.erb
    format.json { render json: @widget }
{% endhighlight %}

And the output will look like this:

def show
  @widget = Widget(params[:id])
  respond_to do |format|
    format.html # show.html.erb
    format.json { render json: @widget }
ProTip™: Show line numbers

You can make code snippets include line-numbers by adding the word linenos to the end of the opening highlight tag like this: {% highlight ruby linenos %}.

These basics should be enough to get you started writing your first posts. When you’re ready to dig into what else is possible, you might be interested in doing things like customizing post permalinks or using custom variables in your posts and elsewhere on your site.

Chapter 2.3 - Working with drafts

Drafts are posts without a date. They’re posts you’re still working on and don’t want to publish yet. To get up and running with drafts, create a _drafts folder in your site’s root (as described in the site structure section) and create your first draft:

|-- _drafts/
|   |-- a-draft-post.md

To preview your site with drafts, simply run jekyll serve or jekyll build with the --drafts switch. Each will be assigned the value modification time of the draft file for its date, and thus you will see currently edited drafts as the latest posts.

Chapter 2.4 - Creating pages

In addition to writing posts, another thing you may want to do with your Jekyll site is create static pages. By taking advantage of the way Jekyll copies files and directories, this is easy to do.


Just about every web server configuration you come across will look for an HTML file called index.html (by convention) in the site’s root folder and display that as the homepage. Unless the web server you’re using is configured to look for some different filename as the default, this file will turn into the homepage of your Jekyll-generated site.

ProTip™: Use layouts on your homepage

Any HTML file on your site can use layouts and/or includes, even the homepage. Common content, like headers and footers, make excellent candidates for extraction into a layout.

Where additional pages live

Where you put HTML or Markdown files for pages depends on how you want the pages to work. There are two main ways of creating pages:

Both methods work fine (and can be used in conjunction with each other), with the only real difference being the resulting URLs.

Named HTML files

The simplest way of adding a page is just to add an HTML file in the root directory with a suitable name for the page you want to create. For a site with a homepage, an about page, and a contact page, here’s what the root directory and associated URLs might look like:

|-- _config.yml
|-- _includes/
|-- _layouts/
|-- _posts/
|-- _site/
|-- about.html    # => http://example.com/about.html
|-- index.html    # => http://example.com/
|-- other.md      # => http://example.com/other.html
└── contact.html  # => http://example.com/contact.html

Named folders containing index HTML files

There is nothing wrong with the above method. However, some people like to keep their URLs free from things like filename extensions. To achieve clean URLs for pages using Jekyll, you simply need to create a folder for each top-level page you want, and then place an index.html file in each page’s folder. This way the page URL ends up being the folder name, and the web server will serve up the respective index.html file. Here’s an example of what this structure might look like:

├── _config.yml
├── _includes/
├── _layouts/
├── _posts/
├── _site/
├── about/
|   └── index.html  # => http://example.com/about/
├── contact/
|   └── index.html  # => http://example.com/contact/
|── other/
|   └── index.md    # => http://example.com/other/
└── index.html      # => http://example.com/

This approach may not suit everyone, but for people who like clean URLs it’s simple and it works. In the end the decision is yours!

ProTip™: Use permalink Front Matter Variable

Clean URLs can also be achieved using the permalink front matter variable. In the example above, using the first method, you can get URL http://example.com/other for the file other.md by setting this at the top of the file: permalink: /other

Chapter 2.5 - Static Files

In addition to renderable and convertible content, we also have static files.

A static file is a file that does not contain any YAML front matter. These include images, PDFs, and other un-rendered content.

They’re accessible in Liquid via site.static_files and contain the following metadata:

Variable Description


The relative path to the file.


The `Time` the file was last modified.


The extension name for the file, e.g. .jpg for image.jpg

Chapter 2.6 - Variables

Jekyll traverses your site looking for files to process. Any files with YAML front matter are subject to processing. For each of these files, Jekyll makes a variety of data available via the Liquid templating system. The following is a reference of the available data.

Global Variables

Variable Description


Sitewide information + configuration settings from _config.yml. See below for details.


Page specific information + the YAML front matter. Custom variables set via the YAML Front Matter will be available here. See below for details.


In layout files, the rendered content of the Post or Page being wrapped. Not defined in Post or Page files.


When the paginate configuration option is set, this variable becomes available for use. See Pagination for details.

Site Variables

Variable Description


The current time (when you run the jekyll command).


A list of all Pages.


A reverse chronological list of all Posts.


If the page being processed is a Post, this contains a list of up to ten related Posts. By default, these are the ten most recent posts. For high quality but slow to compute results, run the jekyll command with the --lsi (latent semantic indexing) option. Also note GitHub Pages does not support the lsi option when generating sites.


A list of all static files (i.e. files not processed by Jekyll's converters or the Liquid renderer). Each file has three properties: path, modified_time and extname.


A subset of `site.pages` listing those which end in `.html`.


A subset of `site.static_files` listing those which end in `.html`.


A list of all the collections.


A list containing the data loaded from the YAML files located in the _data directory.


A list of all the documents in every collection.


The list of all Posts in category CATEGORY.


The list of all Posts with tag TAG.


All the variables set via the command line and your _config.yml are available through the site variable. For example, if you have url: http://mysite.com in your configuration file, then in your Posts and Pages it will be stored in site.url. Jekyll does not parse changes to _config.yml in watch mode, you must restart Jekyll to see changes to variables.

Page Variables

Variable Description


The content of the Page, rendered or un-rendered depending upon what Liquid is being processed and what page is.


The title of the Page.


The un-rendered excerpt of the Page.


The URL of the Post without the domain, but with a leading slash, e.g. /2008/12/14/my-post.html


The Date assigned to the Post. This can be overridden in a Post’s front matter by specifying a new date/time in the format YYYY-MM-DD HH:MM:SS (assuming UTC), or YYYY-MM-DD HH:MM:SS +/-TTTT (to specify a time zone using an offset from UTC. e.g. 2008-12-14 10:30:00 +0900).


An identifier unique to the Post (useful in RSS feeds). e.g. /2008/12/14/my-post


The list of categories to which this post belongs. Categories are derived from the directory structure above the _posts directory. For example, a post at /work/code/_posts/2008-12-24-closures.md would have this field set to ['work', 'code']. These can also be specified in the YAML Front Matter.


The list of tags to which this post belongs. These can be specified in the YAML Front Matter.


The path to the raw post or page. Example usage: Linking back to the page or post’s source on GitHub. This can be overridden in the YAML Front Matter.


The next post relative to the position of the current post in site.posts. Returns nil for the last entry.


The previous post relative to the position of the current post in site.posts. Returns nil for the first entry.

ProTip™: Use Custom Front Matter

Any custom front matter that you specify will be available under page. For example, if you specify custom_css: true in a page’s front matter, that value will be available as page.custom_css.


Variable Description


Number of Posts per page.


Posts available for that page.


Total number of Posts.


Total number of Pages.


The number of the current page.


The number of the previous page.


The path to the previous page.


The number of the next page.


The path to the next page.

Paginator variable availability

These are only available in index files, however they can be located in a subdirectory, such as /blog/index.html.

Chapter 2.7 - Collections

Collections support is unstable and may change

This is an experimental feature and the API may change until the feature stabilizes.

Not everything is a post or a page. Maybe you want to document the various methods in your open source project, members of a team, or talks at a conference. Collections allow you to define a new type of document that behave like Pages or Posts do normally, but also have their own unique properties and namespace.

Using Collections

Step 1: Tell Jekyll to read in your collection

Add the following to your site’s _config.yml file, replacing my_collection with the name of your collection:

- my_collection

You can optionally specify metadata for your collection in the configuration:

    foo: bar

Default attributes can also be set for a collection:

  - scope:
      path: ""
      type: my_collection
      layout: page

Step 2: Add your content

Create a corresponding folder (e.g. <source>/_my_collection) and add documents. YAML Front Matter is read in as data if it exists, and everything after it is stuck in the Document’s content attribute. If no YAML Front Matter is provided, Jekyll will not generate the file in your collection.

Be sure to name your directories correctly

The folder must be named identically to the collection you defined in your _config.yml file, with the addition of the preceding _ character.

Step 3: Optionally render your collection’s documents into independent files

If you’d like Jekyll to create a public-facing, rendered version of each document in your collection, set the output key to true in your collection metadata in your _config.yml:

    output: true

This will produce a file for each document in the collection. For example, if you have _my_collection/some_subdir/some_doc.md, it will be rendered using Liquid and the Markdown converter of your choice and written out to <dest>/my_collection/some_subdir/some_doc.html.

As for posts with Permalinks, the document URL can be customized by setting permalink metadata for the collection:

    output: true
    permalink: /awesome/:path/

For example, if you have _my_collection/some_subdir/some_doc.md, it will be written out to <dest>/awesome/some_subdir/some_doc/index.html.

Don't forget to add YAML for processing

Files in collections that do not have front matter are treated as static files and simply copied to their output location without processing.

Variable Description


Label of the containing collection.


Path to the document relative to the collection's directory.


The document's base filename, with every sequence of spaces and non-alphanumeric characters replaced by a hyphen.


The document's lowercase title (as defined in its front matter), with every sequence of spaces and non-alphanumeric characters replaced by a hyphen. If the document does not define a title in its front matter, this is equivalent to name.


Extension of the output file.

Liquid Attributes


Each collection is accessible via the site Liquid variable. For example, if you want to access the albums collection found in _albums, you’d use site.albums. Each collection is itself an array of documents (e.g. site.albums is an array of documents, much like site.pages and site.posts). See below for how to access attributes of those documents.

The collections are also available under site.collections, with the metadata you specified in your _config.yml (if present) and the following information:

Variable Description


The name of your collection, e.g. my_collection.


An array of documents.


An array of static files in the collection.


The path to the collection's source directory, relative to the site source.


The full path to the collections's source directory.


Whether the collection's documents will be output as individual files.


In addition to any YAML Front Matter provided in the document’s corresponding file, each document has the following attributes:

Variable Description


The (unrendered) content of the document. If no YAML Front Matter is provided, Jekyll will not generate the file in your collection. If YAML Front Matter is used, then this is all the contents of the file after the terminating `---` of the front matter.


The rendered output of the document, based on the content.


The full path to the document's source file.


The path to the document's source file relative to the site source.


The URL of the rendered collection. The file is only written to the destination when the name of the collection to which it belongs is included in the render key in the site's configuration file.


The name of the document's collection.

Accessing Collection Attributes

Attributes from the YAML front matter can be accessed as data anywhere in the site. Using the above example for configuring a collection as site.albums, one might have front matter in an individual file structured as follows (which must use a supported markup format, and cannot be saved with a .yaml extension):

title: "Josquin: Missa De beata virgine and Missa Ave maris stella"
artist: "The Tallis Scholars"
director: "Peter Phillips"
  - title: "Missa De beata virgine"
    composer: "Josquin des Prez"
      - title: "Kyrie"
        duration: "4:25"
      - title: "Gloria"
        duration: "9:53"
      - title: "Credo"
        duration: "9:09"
      - title: "Sanctus & Benedictus"
        duration: "7:47"
      - title: "Agnus Dei I, II & III"
        duration: "6:49"

Every album in the collection could be listed on a single page with a template:

{% for album in site.albums %}
  <h2>{{ album.title }}</h2>
  <p>Performed by {{ album.artist }}{% if album.director %}, directed by {{ album.director }}{% endif %}</p>
  {% for work in album.works %}
    <h3>{{ work.title }}</h3>
    <p>Composed by {{ work.composer }}</p>
    {% for track in work.tracks %}
      <li>{{ track.title }} ({{ track.duration }})</li>
    {% endfor %}
  {% endfor %}
{% endfor %}

Chapter 2.8 - Data Files

In addition to the built-in variables available from Jekyll, you can specify your own custom data that can be accessed via the Liquid templating system.

Jekyll supports loading data from YAML, JSON, and CSV files located in the _data directory. Note that CSV files must contain a header row.

This powerful feature allows you to avoid repetition in your templates and to set site specific options without changing _config.yml.

Plugins/themes can also leverage Data Files to set configuration variables.

The Data Folder

As explained on the directory structure page, the _data folder is where you can store additional data for Jekyll to use when generating your site. These files must be YAML files (using either the .yml, .yaml, .json or csv extension) and they will be accessible via site.data.

Example: List of members

Here is a basic example of using Data Files to avoid copy-pasting large chunks of code in your Jekyll templates:

In _data/members.yml:

- name: Tom Preston-Werner
  github: mojombo

- name: Parker Moore
  github: parkr

- name: Liu Fengyun
  github: liufengyun

Or _data/members.csv:

Tom Preston-Werner,mojombo
Parker Moore,parkr
Liu Fengyun,liufengyun

This data can be accessed via site.data.members (notice that the filename determines the variable name).

You can now render the list of members in a template:

{% for member in site.data.members %}
    <a href="https://github.com/{{ member.github }}">
      {{ member.name }}
{% endfor %}

Example: Organizations

Data files can also be placed in sub-folders of the _data folder. Each folder level will be added to a variable’s namespace. The example below shows how GitHub organizations could be defined separately in a file under the orgs folder:

In _data/orgs/jekyll.yml:

username: jekyll
name: Jekyll
  - name: Tom Preston-Werner
    github: mojombo

  - name: Parker Moore
    github: parkr

In _data/orgs/doeorg.yml:

username: doeorg
name: Doe Org
  - name: John Doe
    github: jdoe

The organizations can then be accessed via site.data.orgs, followed by the file name:

{% for org_hash in site.data.orgs %}
{% assign org = org_hash[1] %}
    <a href="https://github.com/{{ org.username }}">
      {{ org.name }}
    ({{ org.members | size }} members)
{% endfor %}

Example: Accessing a specific author

Pages and posts can also access a specific data item. The example below shows how to access a specific item:


    name: David Smith
    twitter: DavidSilvaSmith

The author can then be specified as a page variable in a post’s frontmatter:

title: sample post
author: dave

{% assign author = site.data.people[page.author] %}
<a rel="author"
  href="{{ author.twitter }}"
  title="{{ author.name }}">
    {{ author.name }}

Chapter 2.9 - Assets

Jekyll provides built-in support for Sass and can work with CoffeeScript via a Ruby gem. In order to use them, you must first create a file with the proper extension name (one of .sass, .scss, or .coffee) and start the file with two lines of triple dashes, like this:


// start content
  font-size: 1.2em

Jekyll treats these files the same as a regular page, in that the output file will be placed in the same directory that it came from. For instance, if you have a file named css/styles.scss in your site’s source folder, Jekyll will process it and put it in your site’s destination folder under css/styles.css.

Jekyll processes all Liquid filters and tags in asset files

If you are using Mustache or another JavaScript templating language that conflicts with the Liquid template syntax, you will need to place {% raw %} and {% endraw %} tags around your code.


Jekyll allows you to customize your Sass conversion in certain ways.

Place all your partials in your sass_dir, which defaults to <source>/_sass. Place your main SCSS or Sass files in the place you want them to be in the output file, such as <source>/css. For an example, take a look at this example site using Sass support in Jekyll.

If you are using Sass @import statements, you’ll need to ensure that your sass_dir is set to the base directory that contains your Sass files. You can do that thusly:

    sass_dir: _sass

The Sass converter will default the sass_dir configuration option to _sass.

The sass_dir is only used by Sass

Note that the sass_dir becomes the load path for Sass imports, nothing more. This means that Jekyll does not know about these files directly, so any files here should not contain the YAML Front Matter as described above nor will they be transformed as described above. This folder should only contain imports.

You may also specify the output style with the style option in your _config.yml file:

    style: compressed

These are passed to Sass, so any output style options Sass supports are valid here, too.


To enable Coffeescript in Jekyll 3.0 and up you must

 - jekyll-coffeescript

Part 3 - Customization

Chapter 3.1 - Templates

Jekyll uses the Liquid templating language to process templates. All of the standard Liquid tags and filters are supported. Jekyll even adds a few handy filters and tags of its own to make common tasks easier.


Description Filter and Output

Date to XML Schema

Convert a Date into XML Schema (ISO 8601) format.

{{ site.time | date_to_xmlschema }}


Date to RFC-822 Format

Convert a Date into the RFC-822 format used for RSS feeds.

{{ site.time | date_to_rfc822 }}

Mon, 07 Nov 2008 13:07:54 -0800

Date to String

Convert a date to short format.

{{ site.time | date_to_string }}

07 Nov 2008

Date to Long String

Format a date to long format.

{{ site.time | date_to_long_string }}

07 November 2008


Select all the objects in an array where the key has the given value.

{{ site.members | where:"graduation_year","2014" }}

Group By

Group an array's items by a given property.

{{ site.members | group_by:"graduation_year" }}

[{"name"=>"2013", "items"=>[...]}, {"name"=>"2014", "items"=>[...]}]

XML Escape

Escape some text for use in XML.

{{ page.content | xml_escape }}

CGI Escape

CGI escape a string for use in a URL. Replaces any special characters with appropriate %XX replacements.

{{ "foo,bar;baz?" | cgi_escape }}


URI Escape

URI escape a string.

{{ "foo, bar \baz?" | uri_escape }}


Number of Words

Count the number of words in some text.

{{ page.content | number_of_words }}


Array to Sentence

Convert an array into a sentence. Useful for listing tags.

{{ page.tags | array_to_sentence_string }}

foo, bar, and baz


Convert a Markdown-formatted string into HTML.

{{ page.excerpt | markdownify }}


Convert "quotes" into “smart quotes.”

{{ page.title | smartify }}

Converting Sass/SCSS

Convert a Sass- or SCSS-formatted string into CSS.

{{ some_scss | scssify }} {{ some_sass | sassify }}


Convert a string into a lowercase URL "slug". See below for options.

{{ "The _config.yml file" | slugify }}


{{ "The _config.yml file" | slugify: 'pretty' }}


Data To JSON

Convert Hash or Array to JSON.

{{ site.data.projects | jsonify }}


Sort an array. Optional arguments for hashes: 1. property name 2. nils order (first or last).

{{ page.tags | sort }}

{{ site.posts | sort: 'author' }}

{{ site.pages | sort: 'title', 'last' }}


Pick a random value from an array. Optional: pick multiple values.

{{ site.pages | sample }}

{{ site.pages | sample:2 }}

Options for the slugify filter

The slugify filter accepts an option, each specifying what to filter. The default is default. They are as follows (with what they filter):



If you have small page fragments that you wish to include in multiple places on your site, you can use the include tag.

{% include footer.html %}

Jekyll expects all include files to be placed in an _includes directory at the root of your source directory. This will embed the contents of <source>/_includes/footer.html into the calling file.

ProTip™: Use variables as file name

The name of the file you wish to embed can be literal (as in the example above), or you can use a variable, using liquid-like variable syntax as in {% include {{my_variable}} %}.

You can also pass parameters to an include. Omit the quotation marks to send a variable’s value. Liquid curly brackets should not be used here:

{% include footer.html param="value" variable-param=page.variable %}

These parameters are available via Liquid in the include:

{{ include.param }}

Including files relative to another file

You can also choose to include file fragments relative to the current file:

{% include_relative somedir/footer.html %}

You won’t need to place your included content within the _includes directory. Instead, the inclusion is specifically relative to the file where the tag is being used. For example, if _posts/2014-09-03-my-file.markdown uses the include_relative tag, the included file must be within the _posts directory, or one of its subdirectories. You cannot include files in other locations.

All the other capabilities of the include tag are available to the include_relative tag, such as using variables.

Code snippet highlighting

Jekyll has built in support for syntax highlighting of over 60 languages thanks to Rouge. Rouge is the default highlighter in Jekyll 3 and above. To use it in Jekyll 2, set highlighter to rouge and ensure the rouge gem is installed properly.

Alternatively, you can use Pygments to highlight your code snippets. To use Pygments, you must have Python installed on your system, have the pygments.rb gem installed and set highlighter to pygments in your site’s configuration file. Pygments supports over 100 languages

To render a code block with syntax highlighting, surround your code as follows:

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

The argument to the highlight tag (ruby in the example above) is the language identifier. To find the appropriate identifier to use for the language you want to highlight, look for the “short name” on the Rouge wiki or the Pygments’ Lexers page.

Line numbers

There is a second argument to highlight called linenos that is optional. Including the linenos argument will force the highlighted code to include line numbers. For instance, the following code block would include line numbers next to each line:

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

Stylesheets for syntax highlighting

In order for the highlighting to show up, you’ll need to include a highlighting stylesheet. For an example stylesheet you can look at syntax.css. These are the same styles as used by GitHub and you are free to use them for your own site. If you use linenos, you might want to include an additional CSS class definition for the .lineno class in syntax.css to distinguish the line numbers from the highlighted code.

Post URL

If you would like to include a link to a post on your site, the post_url tag will generate the correct permalink URL for the post you specify.

{% post_url 2010-07-21-name-of-post %}

If you organize your posts in subdirectories, you need to include subdirectory path to the post:

{% post_url /subdir/2010-07-21-name-of-post %}

There is no need to include the file extension when using the post_url tag.

You can also use this tag to create a link to a post in Markdown as follows:

[Name of Link]({% post_url 2010-07-21-name-of-post %})


Use the gist tag to easily embed a GitHub Gist onto your site. This works with public or secret gists:

{% gist parkr/931c1c8d465a04042403 %}

You may also optionally specify the filename in the gist to display:

{% gist parkr/931c1c8d465a04042403 jekyll-private-gist.markdown %}

To use the gist tag, you’ll need to add the jekyll-gist gem to your project.

Chapter 3.2 - Permalinks

Jekyll supports a flexible way to build your site’s URLs. You can specify the permalinks for your site through the Configuration or in the YAML Front Matter for each post. You’re free to choose one of the built-in styles to create your links or craft your own. The default style is date.

Permalinks are constructed by creating a template URL where dynamic elements are represented by colon-prefixed keywords. For example, the default date permalink is defined according to the format /:categories/:year/:month/:day/:title.html.

Template variables

Variable Description


Year from the Post’s filename


Month from the Post’s filename


Month from the Post’s filename without leading zeros.


Day from the Post’s filename


Day from the Post’s filename without leading zeros.


Year from the Post’s filename without the century.


Hour of the day, 24-hour clock, zero-padded from the post’s date front matter. (00..23)


Minute of the hour from the post’s date front matter. (00..59)


Second of the minute from the post’s date front matter. (00..59)


Title from the document’s filename. May be overridden via the document’s slug YAML front matter.


Slugified title from the document’s filename ( any character except numbers and letters is replaced as hyphen ). May be overridden via the document’s slug YAML front matter.


The specified categories for this Post. If a post has multiple categories, Jekyll will create a hierarchy (e.g. /category1/category2). Also Jekyll automatically parses out double slashes in the URLs, so if no categories are present, it will ignore this.

While you can specify a custom permalink style using template variables, Jekyll also provides the following built-in styles for convenience.

Permalink Style URL Template









Pages and collections

The permalink configuration setting specifies the permalink style used for posts. Pages and collections each have their own default permalink style; the default style for pages is /:path/:basename and the default for collections is /:collection/:path.

These styles are modified to match the suffix style specified in the post permalink setting. For example, a permalink style of pretty, which contains a trailing slash, will update page permalinks to also contain a trailing slash: /:path/:basename/. A permalink style of date, which contains a trailing file extension, will update page permalinks to also contain a file extension: /:path/:basename:output_ext. The same is true for any custom permalink style.

The permalink for an individual page or collection document can always be overridden in the YAML Front Matter for the page or document. Additionally, permalinks for a given collection can be customized in the collections configuration.

Given a post named: /2009-04-29-slap-chop.md

URL Template Resulting Permalink URL

None specified, or permalink: date









See extensionless permalinks for details.


Jekyll supports permalinks that contain neither a trailing slash nor a file extension, but this requires additional support from the web server to properly serve. When using extensionless permalinks, output files written to disk will still have the proper file extension (typically .html), so the web server must be able to map requests without file extensions to these files.

Both GitHub Pages and the Jekyll’s built-in WEBrick server handle these requests properly without any additional work.

Chapter 3.3 - Pagination

With many websites — especially blogs — it’s very common to break the main listing of posts up into smaller lists and display them over multiple pages. Jekyll offers a pagination plugin, so you can automatically generate the appropriate files and folders you need for paginated listings.

For Jekyll 3, include the jekyll-paginate plugin in your Gemfile and in your _config.yml under gems. For Jekyll 2, this is standard.

Pagination only works within HTML files

Pagination does not work from within Markdown or Textile files from your Jekyll site. Pagination works when called from within the HTML file, named index.html, which optionally may reside in and produce pagination from within a subdirectory, via the paginate_path configuration value.

Enable pagination

To enable pagination for your blog, add a line to the _config.yml file that specifies how many items should be displayed per page:

paginate: 5

The number should be the maximum number of Posts you’d like to be displayed per-page in the generated site.

You may also specify the destination of the pagination pages:

paginate_path: "/blog/page:num/"

This will read in blog/index.html, send it each pagination page in Liquid as paginator and write the output to blog/page:num/, where :num is the pagination page number, starting with 2. If a site has 12 posts and specifies paginate: 5, Jekyll will write blog/index.html with the first 5 posts, blog/page2/index.html with the next 5 posts and blog/page3/index.html with the last 2 posts into the destination directory.

Don't set a permalink

Setting a permalink in the front matter of your blog page will cause pagination to break. Just omit the permalink.

Liquid Attributes Available

The pagination plugin exposes the paginator liquid object with the following attributes:

Attribute Description


current page number


number of posts per page


a list of posts for the current page


total number of posts in the site


number of pagination pages


page number of the previous pagination page, or nil if no previous page exists


path of previous pagination page, or nil if no previous page exists


page number of the next pagination page, or nil if no subsequent page exists


path of next pagination page, or nil if no subsequent page exists

Pagination does not support tags or categories

Pagination pages through every post in the posts variable regardless of variables defined in the YAML Front Matter of each. It does not currently allow paging over groups of posts linked by a common tag or category. It cannot include any collection of documents because it is restricted to posts.

Render the paginated Posts

The next thing you need to do is to actually display your posts in a list using the paginator variable that will now be available to you. You’ll probably want to do this in one of the main pages of your site. Here’s one example of a simple way of rendering paginated Posts in a HTML file:

layout: default
title: My Blog

<!-- This loops through the paginated posts -->
{% for post in paginator.posts %}
  <h1><a href="{{ post.url }}">{{ post.title }}</a></h1>
  <p class="author">
    <span class="date">{{ post.date }}</span>
  <div class="content">
    {{ post.content }}
{% endfor %}

<!-- Pagination links -->
<div class="pagination">
  {% if paginator.previous_page %}
    <a href="{{ paginator.previous_page_path }}" class="previous">Previous</a>
  {% else %}
    <span class="previous">Previous</span>
  {% endif %}
  <span class="page_number ">Page: {{ paginator.page }} of {{ paginator.total_pages }}</span>
  {% if paginator.next_page %}
    <a href="{{ paginator.next_page_path }}" class="next">Next</a>
  {% else %}
    <span class="next ">Next</span>
  {% endif %}
Beware the page one edge-case

Jekyll does not generate a ‘page1’ folder, so the above code will not work when a /page1 link is produced. See below for a way to handle this if it’s a problem for you.

The following HTML snippet should handle page one, and render a list of each page with links to all but the current page.

{% if paginator.total_pages > 1 %}
<div class="pagination">
  {% if paginator.previous_page %}
    <a href="{{ paginator.previous_page_path | prepend: site.baseurl | replace: '//', '/' }}">&laquo; Prev</a>
  {% else %}
    <span>&laquo; Prev</span>
  {% endif %}

  {% for page in (1..paginator.total_pages) %}
    {% if page == paginator.page %}
      <em>{{ page }}</em>
    {% elsif page == 1 %}
      <a href="{{ paginator.previous_page_path | prepend: site.baseurl | replace: '//', '/' }}">{{ page }}</a>
    {% else %}
      <a href="{{ site.paginate_path | prepend: site.baseurl | replace: '//', '/' | replace: ':num', page }}">{{ page }}</a>
    {% endif %}
  {% endfor %}

  {% if paginator.next_page %}
    <a href="{{ paginator.next_page_path | prepend: site.baseurl | replace: '//', '/' }}">Next &raquo;</a>
  {% else %}
    <span>Next &raquo;</span>
  {% endif %}
{% endif %}

Chapter 3.4 - Plugins

Jekyll has a plugin system with hooks that allow you to create custom generated content specific to your site. You can run custom code for your site without having to modify the Jekyll source itself.

Plugins on GitHub Pages

GitHub Pages is powered by Jekyll. However, all Pages sites are generated using the --safe option to disable custom plugins for security reasons. Unfortunately, this means your plugins won’t work if you’re deploying to GitHub Pages.

You can still use GitHub Pages to publish your site, but you’ll need to convert the site locally and push the generated static files to your GitHub repository instead of the Jekyll source files.

Installing a plugin

You have 3 options for installing plugins:

  1. In your site source root, make a _plugins directory. Place your plugins here. Any file ending in *.rb inside this directory will be loaded before Jekyll generates your site.
  2. In your _config.yml file, add a new array with the key gems and the values of the gem names of the plugins you’d like to use. An example:

     gems: [jekyll-coffeescript, jekyll-watch, jekyll-assets]
     # This will require each of these gems automatically.

    Then install your plugins using gem install jekyll-coffeescript jekyll-watch jekyll-assets

  3. Add the relevant plugins to a Bundler group in your Gemfile. An example:

     group :jekyll_plugins do
       gem "my-jekyll-plugin"
       gem "another-jekyll-plugin"

    Now you need to install all plugins from your Bundler group by running single command bundle install

_plugins, _config.yml and Gemfile can be used simultaneously

You may use any of the aforementioned plugin options simultaneously in the same site if you so choose. Use of one does not restrict the use of the others.

Chapter 3.5 - Extras

There are a number of (optional) extra features that Jekyll supports that you may want to install, depending on how you plan to use Jekyll.

Math Support

Kramdown comes with optional support for LaTeX to PNG rendering via MathJax within math blocks. See the Kramdown documentation on math blocks and math support for more details. MathJax requires you to include JavaScript or CSS to render the LaTeX, e.g.

<script src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"></script>

For more information about getting started, check out this excellent blog post.

Alternative Markdown Processors

See the Markdown section on the configuration page for instructions on how to use and configure alternative Markdown processors, as well as how to create custom processors.

Part 4 - Miscellaneous

Chapter 4.1 - Troubleshooting

If you ever run into problems installing or using Jekyll, here are a few tips that might be of help. If the problem you’re experiencing isn’t covered below, please check out our other help resources as well.

Base-URL Problems

If you are using base-url option like:

jekyll serve --baseurl '/blog'

… then make sure that you access the site at:


It won’t work to just access:


Configuration problems

The order of precedence for conflicting configuration settings is as follows:

  1. Command-line flags
  2. Configuration file settings
  3. Defaults

That is: defaults are overridden by options specified in _config.yml, and flags specified at the command-line will override all other settings specified elsewhere.

Markup Problems

The various markup engines that Jekyll uses may have some issues. This page will document them to help others who may run into the same problems.


The latest version, version 2.0, seems to break the use of {{ in templates. Unlike previous versions, using {{ in 2.0 triggers the following error:

'{{' was not properly terminated with regexp: /\}\}/  (Liquid::SyntaxError)


Since v1.0.0, Jekyll has had automatically-generated post excerpts. Since v1.1.0, Jekyll also passes these excerpts through Liquid, which can cause strange errors where references don’t exist or a tag hasn’t been closed. If you run into these errors, try setting excerpt_separator: "" in your _config.yml, or set it to some nonsense string.

Please report issues you encounter!

If you come across a bug, please create an issue on GitHub describing the problem and any work-arounds you find so we can document it here for others.

Part 5 - Appendix

Chapter 5.1 - Plugins

Available Plugins

You can find a few useful plugins at the following locations:








Jekyll Plugins Wanted

If you have a Jekyll plugin that you would like to see added to this list, you should read the contributing page to find out how to make that happen.

Chapter 5.2 - History

3.1.1 / 2016-01-29


Bug Fixes

Development Fixes

3.1.0 / 2016-01-23

Minor Enhancements

Bug Fixes

Development Fixes

Site Enhancements

3.0.2 / 2016-01-20

Bug Fixes

3.0.1 / 2015-11-17

Bug Fixes

Development Fixes

Site Enhancements

3.0.0 / 2015-10-26

Major Enhancements

Minor Enhancements

Bug Fixes

Development Fixes

Site Enhancements

2.5.3 / 2014-12-22

Bug Fixes

Development Fixes

Site Enhancements

2.5.2 / 2014-11-17

Minor Enhancements

Bug Fixes

Site Enhancements

2.5.1 / 2014-11-09

Bug Fixes

Development Fixes

2.5.0 / 2014-11-06

Minor Enhancements

Bug Fixes

Development Fixes

Site Enhancements

2.4.0 / 2014-09-09

Minor Enhancements

Bug Fixes

Development Fixes

Site Enhancements

2.3.0 / 2014-08-10

Minor Enhancements

Bug Fixes

Development Fixes

Site Enhancements

2.2.0 / 2014-07-29

Minor Enhancements

Bug Fixes

Development Fixes

Site Enhancements

2.1.1 / 2014-07-01

Bug Fixes

Site Enhancements

2.1.0 / 2014-06-28

Minor Enhancements

Bug Fixes

Development Fixes

Site Enhancements

2.0.3 / 2014-05-08

Bug Fixes

Site Enhancements

2.0.2 / 2014-05-07

Bug Fixes

Site Enhancements

2.0.1 / 2014-05-06

Bug Fixes

2.0.0 / 2014-05-06

Major Enhancements

Minor Enhancements

Bug Fixes

Development Fixes

Site Enhancements

1.5.1 / 2014-03-27

Bug Fixes

1.5.0 / 2014-03-24

Minor Enhancements

Bug Fixes

Development Fixes

1.4.3 / 2014-01-13

Bug Fixes

1.4.2 / 2013-12-16

Bug Fixes

1.4.1 / 2013-12-09

Bug Fixes

1.4.0 / 2013-12-07

Major Enhancements

Minor Enhancements

Bug Fixes

Development Fixes

Site Enhancements

1.3.1 / 2013-11-26

Minor Enhancements

Bug Fixes

Development Fixes

Site Enhancements

1.3.0 / 2013-11-04

Major Enhancements

Minor Enhancements

Bug Fixes

Development Fixes

Site Enhancements

1.2.1 / 2013-09-14

Minor Enhancements

Bug Fixes

Development Fixes

Site Enhancements

1.2.0 / 2013-09-06

Major Enhancements

Minor Enhancements

Bug Fixes

Development Fixes

Site Enhancements

1.1.2 / 2013-07-25

Bug Fixes

1.1.1 / 2013-07-24

Minor Enhancements

Bug Fixes

Site Enhancements

1.1.0 / 2013-07-14

Major Enhancements

Minor Enhancements

Bug Fixes

Development Fixes

Site Enhancements

1.0.3 / 2013-06-07

Minor Enhancements

Bug Fixes

Site Enhancements

Development Fixes

1.0.2 / 2013-05-12

Major Enhancements

Minor Enhancements

Bug Fixes

Site Enhancements

1.0.1 / 2013-05-08

Minor Enhancements

Bug Fixes

Site Enhancements

Development Fixes

1.0.0 / 2013-05-06

Major Enhancements

Minor Enhancements

Site Enhancements

Development Fixes

0.12.1 / 2013-02-19

Minor Enhancements

0.12.0 / 2012-12-22

Minor Enhancements

0.11.2 / 2011-12-27

0.11.1 / 2011-12-27

0.11.0 / 2011-07-10

Major Enhancements

Minor Enhancements

0.10.0 / 2010-12-16

0.9.0 / 2010-12-15

Minor Enhancements

0.8.0 / 2010-11-22

Minor Enhancements

0.7.0 / 2010-08-24

Minor Enhancements

0.6.2 / 2010-06-25

0.6.1 / 2010-06-24

0.6.0 / 2010-06-23

Major Enhancements

Minor Enhancements

0.5.7 / 2010-01-12

Minor Enhancements

0.5.6 / 2010-01-08

Minor Enhancements

0.5.5 / 2010-01-08

0.5.4 / 2009-08-23

0.5.3 / 2009-07-14

0.5.2 / 2009-06-24

0.5.1 / 2009-05-06

Major Enhancements

0.5.0 / 2009-04-07

Minor Enhancements


Minor Enhancements

0.4.0 / 2009-02-03

Major Enhancements

Minor Enhancements

0.3.0 / 2008-12-24

Major Enhancements

Minor Enhancements

0.2.1 / 2008-12-15

Minor Enhancements

0.2.0 / 2008-12-14

0.1.6 / 2008-12-13

0.1.5 / 2008-12-12

Major Enhancements

Minor Enhancements

0.1.4 / 2008-12-08

0.1.3 / 2008-12-06

0.1.2 / 2008-11-22

0.1.1 / 2008-11-22

0.1.0 / 2008-11-05

0.0.0 / 2008-10-19