Home Blog Jekyll _config.yml: The Complete Configuration Guide
Tutorial

Jekyll _config.yml: The Complete Configuration Guide

Everything you need to know about Jekyll's _config.yml — global settings, build options, plugins, collections, front matter defaults, and real-world examples.

Jekyll _config.yml: The Complete Configuration Guide

_config.yml is the single most important file in a Jekyll project. It controls everything: your site’s URL, which plugins run, how collections are defined, what files are excluded from builds, and any custom data you want available across every template. Understanding it thoroughly is essential for anyone building or customising a Jekyll site.

File location and format

_config.yml lives at the root of your Jekyll project:

my-jekyll-site/
├── _config.yml     ← here
├── _posts/
├── _layouts/
├── _includes/
└── index.html

It uses YAML format — indented key-value pairs. Two spaces per indent level, no tabs.

Important: Jekyll reads _config.yml only at startup. If you change it while running jekyll serve, you must restart the server to see the changes take effect. Content changes in posts and pages hot-reload automatically; config changes do not.

Essential site settings

# Site identity
title: "JekyllHub"
description: "A marketplace for premium and free Jekyll themes."

# URLs — critical to get right
url: "https://jekyllhub.com"       # your production domain with scheme
baseurl: ""                         # subdirectory, if any (e.g. "/blog")

# Contact
email: hello@jekyllhub.com

url vs baseurl

This distinction trips up many Jekyll users.

url is your site’s root domain: https://jekyllhub.com. It is used to construct absolute URLs (for RSS feeds, sitemaps, canonical tags).

baseurl is a subdirectory path if your site does not live at the root of the domain. For a site at https://username.github.io/my-project/, set baseurl: "/my-project". For a site at the root, leave it empty: baseurl: "".

In templates, always use the relative_url or absolute_url filters instead of hardcoding paths — they automatically prepend baseurl:

<a href="/about/">About</a>
<link rel="canonical" href="https://jekyllhub.com/tutorial/2026/06/22/jekyll-config-yml-guide/">

Build settings

# Build
source: .              # where Jekyll reads files (default: current dir)
destination: _site     # where Jekyll writes output (default: _site)

# Markdown
markdown: kramdown
highlighter: rouge     # syntax highlighting engine

# Kramdown options
kramdown:
  input: GFM                        # GitHub Flavoured Markdown
  hard_wrap: false
  syntax_highlighter: rouge
  syntax_highlighter_opts:
    block:
      line_numbers: true

# Liquid
liquid:
  error_mode: warn      # warn | strict | lax
  strict_filters: false
  strict_variables: false

Plugins

List all plugins in the plugins key:

plugins:
  - jekyll-feed          # generates /feed.xml RSS feed
  - jekyll-seo-tag       # adds meta tags, OG tags, JSON-LD
  - jekyll-sitemap       # generates /sitemap.xml
  - jekyll-paginate-v2   # pagination for posts
  - jekyll-redirect-from # add redirects via front matter
  - jekyll-archives      # generates category and tag archive pages

Plugins must also be in your Gemfile:

group :jekyll_plugins do
  gem "jekyll-feed"
  gem "jekyll-seo-tag"
  gem "jekyll-sitemap"
  gem "jekyll-paginate-v2"
end

GitHub Pages note: GitHub Pages only supports a specific list of whitelisted plugins. If deploying to GitHub Pages, check the whitelist. For full plugin support, use Cloudflare Pages, Netlify, or Vercel with a build step.

Collections

Collections let you create custom content types beyond posts and pages:

collections:
  themes:
    output: true                        # generate individual pages for each item
    permalink: /themes/:name/           # URL pattern
  authors:
    output: true
    permalink: /authors/:name/
  showcase:
    output: false                       # data only, no individual pages

With this configuration, files in _themes/ generate pages at /themes/minimal-mistakes/, etc. Files in _showcase/ are available as site.showcase but do not generate pages.

Front matter defaults

Avoid repeating the same front matter on every post with defaults:

defaults:
  # All posts get layout: post and author: Marcus Webb
  - scope:
      path: ""
      type: posts
    values:
      layout: post
      author: Marcus Webb
      toc: true
      featured: false
      comments: true

  # All pages get layout: page
  - scope:
      path: ""
      type: pages
    values:
      layout: page

  # Theme collection items get layout: theme
  - scope:
      path: ""
      type: themes
    values:
      layout: theme

  # Files in a specific directory
  - scope:
      path: "guides"
    values:
      layout: guide
      sidebar: true

  # A specific file
  - scope:
      path: "index.html"
    values:
      layout: home

Specificity rules: more specific scopes override less specific ones. A file-level front matter value always wins over any default.

Excluding and including files

By default, Jekyll excludes dotfiles, Gemfile, Gemfile.lock, node_modules, and a few others. Customise with:

# Exclude from build output
exclude:
  - .sass-cache/
  - .jekyll-cache/
  - Gemfile
  - Gemfile.lock
  - node_modules/
  - vendor/
  - "*.sh"
  - README.md
  - package.json
  - package-lock.json
  - tools/
  - CHANGELOG.md

# Include files that would otherwise be excluded
include:
  - _redirects      # Netlify/Cloudflare redirects file
  - _headers        # Cloudflare/Netlify headers file
  - .htaccess       # Apache config (dotfile, excluded by default)

Pagination

Using jekyll-paginate-v2:

pagination:
  enabled: true
  per_page: 12
  permalink: "/page/:num/"
  title: ":title - Page :num"
  sort_field: "date"
  sort_reverse: true

# Enable autopages for categories and tags
autopages:
  enabled: true
  categories:
    enabled: true
    permalink: "/category/:cat/"
    layouts:
      - "category.html"
  tags:
    enabled: false

SEO and analytics settings

Using jekyll-seo-tag:

# Used by jekyll-seo-tag
title: "JekyllHub"
tagline: "Find Your Perfect Jekyll Theme"
description: "Browse free and premium Jekyll themes for blogs, portfolios, and business sites."
url: "https://jekyllhub.com"
logo: /assets/images/logo.png
author:
  name: Marcus Webb
  email: marcus@jekyllhub.com
  twitter: marcuswebb

twitter:
  username: jekyllhub
  card: summary_large_image

social:
  name: JekyllHub
  links:
    - https://twitter.com/jekyllhub
    - https://github.com/jekyllhub

# Analytics (custom keys — not built-in Jekyll)
google_analytics: "G-XXXXXXXXXX"
plausible_domain: "jekyllhub.com"

# Newsletter (custom)
sendy_url: "https://sendpress.org/s/subscribe"
sendy_list_id: "YOUR_LIST_ID"

Jekyll Feed settings

feed:
  posts_limit: 20
  excerpt_only: false
  collections:
    - posts

Sass/SCSS settings

sass:
  sass_dir: _sass          # where .scss partials live
  style: compressed        # compressed | expanded | nested | compact
  load_paths:
    - _sass
    - node_modules         # if using npm packages

Custom data available in all templates

Any key in _config.yml is available as site.keyname throughout all templates. Use this to store site-wide settings:

# Custom site settings
nav_links:
  - title: Browse Themes
    url: /themes/
  - title: Blog
    url: /blog/
  - title: Showcase
    url: /showcase/

social_links:
  github: https://github.com/jekyllhub
  twitter: https://twitter.com/jekyllhub

support_email: support@jekyllhub.com
theme_submission_url: /submit/

Access in templates:


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

<a href="{{ site.social_links.github }}">GitHub</a>

Environment-specific configuration

Use multiple config files for different environments:

# _config.yml (base, committed to repo)
title: "JekyllHub"
url: "https://jekyllhub.com"
google_analytics: ""

# _config.development.yml (local overrides, not committed)
url: "http://localhost:4000"
google_analytics: ""

Run Jekyll with multiple configs — later files override earlier ones:

# Development
bundle exec jekyll serve --config _config.yml,_config.development.yml

# Production
JEKYLL_ENV=production bundle exec jekyll build

Serving options

Settings for jekyll serve:

# Local server
port: 4000
host: "127.0.0.1"
livereload: true          # auto-refresh browser on changes
open_url: true            # open browser automatically

# Show drafts during development
show_drafts: false        # set to true or use --drafts flag
future: false             # show posts with future dates
unpublished: false        # show unpublished posts

Timezone

timezone: "Europe/London"    # IANA timezone name

This affects how page.date is interpreted and how dates are formatted. Set it to your local timezone to avoid date-off-by-one issues.

# For posts
permalink: /:categories/:year/:month/:day/:title/

# Common permalink styles:
permalink: pretty          # /year/month/day/title/
permalink: date            # /year/month/day/title.html
permalink: ordinal         # /year/ordinal/title.html
permalink: weekdate        # /year/week/short_day/title/
permalink: none            # /title.html

A common setup for blogs:

permalink: /blog/:title/

This gives clean, category-free URLs like /blog/jekyll-front-matter-guide/.

Full example _config.yml

# ─── Site Identity ───────────────────────────────────────────────────────
title: "JekyllHub"
tagline: "Find Your Perfect Jekyll Theme"
description: "A marketplace for premium and free Jekyll themes  for blogs, portfolios, documentation, and business sites."
url: "https://jekyllhub.com"
baseurl: ""
email: hello@jekyllhub.com
author: "Marcus Webb"
logo: /assets/images/logo.png

# ─── Build ───────────────────────────────────────────────────────────────
timezone: "Europe/London"
markdown: kramdown
highlighter: rouge
permalink: /blog/:title/

kramdown:
  input: GFM
  syntax_highlighter: rouge

# ─── Plugins ─────────────────────────────────────────────────────────────
plugins:
  - jekyll-feed
  - jekyll-seo-tag
  - jekyll-sitemap
  - jekyll-paginate-v2
  - jekyll-redirect-from

# ─── Collections ─────────────────────────────────────────────────────────
collections:
  themes:
    output: true
    permalink: /themes/:name/
  authors:
    output: true
    permalink: /authors/:name/

# ─── Defaults ────────────────────────────────────────────────────────────
defaults:
  - scope:
      path: ""
      type: posts
    values:
      layout: post
      toc: true
      featured: false
  - scope:
      path: ""
      type: pages
    values:
      layout: page
  - scope:
      path: ""
      type: themes
    values:
      layout: theme
  - scope:
      path: ""
      type: authors
    values:
      layout: author

# ─── Pagination ──────────────────────────────────────────────────────────
pagination:
  enabled: true
  per_page: 12
  permalink: "/page/:num/"
  sort_field: date
  sort_reverse: true

# ─── Analytics ───────────────────────────────────────────────────────────
google_analytics: "G-XXXXXXXXXX"

# ─── Newsletter ──────────────────────────────────────────────────────────
sendy_url: "https://sendpress.org/s/subscribe"
sendy_list_id: ""
sendy_waitlist_id: ""

# ─── Exclude ─────────────────────────────────────────────────────────────
exclude:
  - Gemfile
  - Gemfile.lock
  - node_modules/
  - vendor/
  - tools/
  - package.json
  - README.md

include:
  - _redirects
  - _headers

The _config.yml file is the control panel of your Jekyll site. Mastering it means being able to change almost any aspect of how Jekyll builds and serves your content without touching a single template file.

Share LinkedIn