An opinionated guide to common Jekyll design patterns and anti-patterns.
Note: The book edition is still an early release and a work-in-progess.
This is the (official) style guide 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.
Thanks to Ben Balter and all style guide contributors for making it all possible.
Jekyll’s incredibly flexible, but in some instances, the lack of common conventions make things harder for users.
For one, there are many common design patterns that are still relatively unknown to new users (e.g., using
permalink: /about/ in
about.md, rather than creating
For another, when writing a plugin or theme intended to be used across sites, should it look for
site.tagline? Moar options, moar problems.
This style guide aims to make it easier to create awesome Jekyll sites by codifying and surfacing Jekyll best practices.
This style guide is intended to be a collaborative resource for the Jekyll community. Please help improve it.
If you’d like to propose a change to the style guide, please suggest the added or modified rule as a pull request so that the community can discuss the merits of the proposed change a bit more tangibly.
When it comes to software, there are a lot of personal preferences, and Jekyll is no exception. Whenever possible, please try to explain each rule’s logical justification and the rule the value provides to end users.
Config files should be YAML.
Prefer multi-line arrays for readability and version control purposes.
numbers: - one - two - three
numbers: [one, two, three]
Use the following site-wide variables, where appropriate:
title- the name of the site. Use
titleand not name to match document and page meta.
description- the site’s tagline or subtitle
The site’s base URL is only to be used when the resulting site lives at a subpath of the domain. Otherwise, the subpath should be nil, not
example.com/blog, you should have a
example.com, you should not set a
baseurl. Not even
When your site is intended to be hosted on GitHub Pages, prefer values in the
site.github namespace to manually specified values. In additional to reducing configuration noise, this will save headache if your repository is renamed, you add a CNAME, the project is forked, or if you preview the site locally.
site.github.url when using GitHub Pages. To ensure your site renders properly locally, add the following to your site’s config (which will be overridden by GitHub Pages):
github: url: http://localhost:4000
When a post contains markdown, use
.md for the file extension. While
.markdown will still render, many implementations assume three- to four-letter extension names, as will many developers.
Whenever possible, avoid prefixing page filenames with numbers (e.g.,
02-contact). When order must be specified, prefer other means of ordering page navigation such as storing the ordering in YAML front matter, the site’s config or a data file.
Filename-based ordering makes it difficult to add additional pages cleanly, and may trick novice Jekyll users into thinking such numbers have special meaning (like Pages date prefixes do). More often than not, hard coded navigation (potentially in an include) will suffice.
Your site should have a
.gitignore file, with a minimum of the following Git-ignored paths, which are local, unversioned artifacts created during the Jekyll build process:
_site .sass-cache .jekyll-metadata
If the built site is served via GitHub Pages, you should also add
Gemfile.lock to your site’s
github-pages gem strictly versions dependencies, rendering versioning the lockfile unnecessary, and potentially could result in using outdated gem versions.
Post are to be used for the site’s primary (or only) chronologically ordered content. Examples of this may be blog posts or news articles.
Use collections for any logically grouped content, chronological or not, that are not posts. Examples of collections might be employees, puppies, or releases. Each logical group of documents should be their own collection. For more information, see explain like I’m five: Jekyll collections.
Use pages for any non-chronological content that cannot be logically grouped together (and thus are not posts or collections). Examples of pages might be the index page, an about page, a contact us page, or a resume page.
Use data (YAML, JSON, or CSV files in the
_data folder) for site-wide configuration, settings, or other primarily static information. Examples of data might be the site’s authors, a list of press clippings, or a glossary of terms. Generally, the distinction between collections and data is that data files do not have a large markdown body, and live in a single file, rather than multiple files. Unlike collections, data files cannot render as individual files.
The site’s primary layout should be called
default.html. Where possible, all other layouts should inherit from the default layout.
Unless unusually complex, do not delegate header and footer markup to dedicated includes. This adds unnecessary complexity for simple sites. While many WordPress themes, for example, may do this, Rails, and the majority of the Ruby world (from which Jekyll gets its roots), do not.
Regardless of the permalink structure, prefer collection and per-file permalinks that end with a trailing slash, rather than
.html. Pretty permalinks are intended to be read by humans, not machines, and contain no extraneous information (format information otherwise conveyed by the response header).
permalink: pretty permalink: /:year/:month/:day/:title/
permalink: date permalink: /:categories/:year/:y_day/:title.html
Don’t hide markdown files in subfolders to achieve pretty permalinks. Doing so is unnecessary, adds additional steps to most editing workflows, and makes distinguishing between numerous
index.md files more difficult, when open in a text editor. Generated permalinks should have a logical relationship to the source filename.
about.md (accessible as
--- title: About permalink: `/about/` ---
about/index.md (accessible as
--- title: About ---
For common use cases, prefer plugins with shared templates or logic over hard-coded HTML.
Prefer Gem-based plugins over individual files in the
When writing plugins that may be run with untrusted user content, prefer liquid tempting and logic over Ruby, and internal Jekyll implementations over plugin-specific methods to minimize the surface area that needs to be secured.
Plugins should be descriptively named and preceded by
Plugins should be namespaced within the
Jekyll module. The top-level class should not be prefixed with
Unless you need to specify the time your post was published, prefer the date in the filename to explicit YAML frontmatter post dates. This reduces duplication of information and reduces frontmatter noise that may not otherwise be necessary in most implementations.
If your site is hosted in a GitHub Pages repository, prefer the following:
If your site uses only the
gh-pages branch, set the
gh-pages branch to your default branch and delete the
master branch. This will ensure that when users visit your site’s repository, they see your site’s content, and that you don’t accidentally commit to the
master branch, allowing the two to get out of sync. It will also set the default target for pull requests, ensuring contributors can’t do the same.
Prefer backtick-style fenced-code blocks to Liquid-style
highlight tags. This allows the markdown to render both within Jekyll and to be previewed on GitHub.com. Note: You may need to configure your markdown engine to properly support them. For Kramdown, that’s:
kramdown: input: GFM