Skip to content

Jekyll — Static Site Generation with Ruby and Liquid Templates

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you will learn about Jekyll. We cover key concepts, practical examples, and best practices to help you master this topic.

Jekyll is a Ruby-based static site generator that converts markdown content into static HTML using Liquid templates and frontmatter metadata.

What You'll Learn

By the end of this tutorial, you'll understand Jekyll's architecture, how to use Liquid templates, organize collections and posts, configure plugins, and deploy Jekyll sites.

Why It Matters

Jekyll pioneered the modern SSG approach and powers GitHub Pages natively. Understanding Jekyll gives you access to a mature ecosystem with seamless GitHub integration and a vast plugin library.

Real-World Use

A team blog uses Jekyll with GitHub Pages for zero-cost hosting. Team members write posts in markdown, push to GitHub, and the site auto-builds and deploys. Tags, categories, and archives are generated automatically from frontmatter.

Jekyll Architecture

graph TD
    A[Jekyll Project] --> B[_config.yml]
    A --> C[_posts/]
    A --> D[_layouts/]
    A --> E[_includes/]
    A --> F[assets/]
    A --> G[_data/]
    A --> H[_plugins/]
    C --> I[Markdown posts
with frontmatter] D --> J[Liquid templates] E --> K[Partials
header, footer, nav] A --> L[jekyll build] F --> L G --> L H --> L I --> L J --> L K --> L L --> M[_site/ — Static output] style L fill:#e67e22,color:#fff style M fill:#27ae60,color:#fff

Jekyll Configuration

# _config.yml — Jekyll configuration
title: My Jekyll Site
email: team@example.com
description: A blog built with Jekyll and hosted on GitHub Pages
baseurl: "/blog"
url: "https://example.com"

# Build settings
markdown: kramdown
highlighter: rouge
permalink: /:year/:month/:day/:title/

# Collections
collections:
  projects:
    output: true
    permalink: /projects/:path/
  team:
    output: false

# Default frontmatter
defaults:
  - scope:
      path: ""
      type: "posts"
    values:
      layout: "post"
      author: "DodaTech"
  - scope:
      path: ""
      type: "projects"
    values:
      layout: "project"

# Plugins
plugins:
  - jekyll-feed
  - jekyll-sitemap
  - jekyll-seo-tag
  - jekyll-paginate

# Pagination
paginate: 5
paginate_path: "/page/:num/"

Liquid Templates

{% comment %}
_layouts/default.html — Base layout
{% endcomment %}
<!DOCTYPE html>
<html lang="{{ site.lang | default: 'en-US' }}">
<head>
    <meta charset="utf-8">
    <title>{% if page.title %}{{ page.title }} — {% endif %}{{ site.title }}</title>
    <meta name="description" content="{{ page.description | default: site.description }}">
    <link rel="stylesheet" href="{{ '/assets/css/main.css' | relative_url }}">
    {% feed_meta %}
    {% seo %}
</head>
<body>
    {% include header.html %}

    <main>
        {{ content }}
    </main>

    {% include footer.html %}
</body>
</html>

{% comment %}
_layouts/post.html — Post layout
{% endcomment %}
---
layout: default
---
<article class="post">
    <header>
        <h1>{{ page.title }}</h1>
        <div class="meta">
            <time datetime="{{ page.date | date_to_xmlschema }}">
                {{ page.date | date: "%B %-d, %Y" }}
            </time>
            {% if page.tags %}
            <div class="tags">
                {% for tag in page.tags %}
                <a href="{{ '/tags/' | append: tag | relative_url }}">{{ tag }}</a>
                {% endfor %}
            </div>
            {% endif %}
        </div>
    </header>

    <div class="content">
        {{ content }}
    </div>
</article>

Content Organization

---
# _posts/2026-06-28-getting-started-with-jekyll.md
layout: post
title: "Getting Started with Jekyll"
date: 2026-06-28 10:00:00 -0400
categories: [tutorial, jekyll]
tags: [static-site, ruby, ssg]
author: DodaTech
description: "Learn how to set up Jekyll, write content, and deploy to GitHub Pages."
image: /assets/images/jekyll-guide.jpg
---

Jekyll takes markdown content, combines it with Liquid templates, and generates a complete static website.

## Installation

Install Jekyll and Bundler:

{% highlight bash %}
gem install jekyll bundler
jekyll new my-site
cd my-site
jekyll serve
{% endhighlight %}

## Frontmatter Variables

Each page and post starts with YAML frontmatter that defines metadata:

{% highlight yaml %}
---
title: My Page
layout: default
permalink: /custom-url/
---
{% endhighlight %}

## Collections

Beyond posts, Jekyll supports custom collections:

{% highlight yaml %}
# _config.yml
collections:
  documentation:
    output: true
{% endhighlight %}

Create files in `_documentation/` directory and access them as `site.documentation`.

Data Files and Includes

{% comment %}
_includes/nav.html — Navigation from data file
{% endcomment %}
<nav class="main-nav">
    <a href="{{ '/' | relative_url }}">Home</a>

    {% for item in site.data.navigation %}
    <a href="{{ item.url | relative_url }}"
       {% if page.url == item.url %}class="active"{% endif %}>
        {{ item.name }}
    </a>
    {% endfor %}
</nav>

{% comment %}
Using _data/team.yml
{% endcomment %}
{% comment %} _data/team.yml content:
- name: Alice
  role: Developer
  github: alicedev
- name: Bob
  role: Designer
  github: bobdesign
{% endcomment %}

<section class="team">
    <h2>Our Team</h2>
    <div class="members">
        {% for member in site.data.team %}
        <div class="member">
            <h3>{{ member.name }}</h3>
            <p>{{ member.role }}</p>
            <a href="https://github.com/{{ member.github }}">@{{ member.github }}</a>
        </div>
        {% endfor %}
    </div>
</section>

Common Mistakes

  1. Not including the date prefix in post filenames. Post files must follow YYYY-MM-DD-title.md format. Jekyll ignores files without the date prefix.
  2. Mixing tabs and spaces in Liquid syntax. Jekyll requires consistent indentation. Use spaces for YAML and be careful with whitespace in Liquid tags.
  3. Using {{ site.baseurl }} when {{ relative_url }} suffices. relative_url is safer and handles subdirectory deployments automatically.
  4. Forgetting to add plugins to the Gemfile. Jekyll plugins must be listed in both _config.yml and Gemfile. Otherwise the build fails on GitHub Pages.
  5. Ignoring the _site directory in .gitignore. The generated _site folder should not be committed. It's rebuilt on every deploy.

Practice Questions

  1. What naming convention must Jekyll post files follow?
  2. How do Liquid templates access site configuration and page metadata?
  3. What is a Jekyll collection and how is it different from posts?
  4. How do you create custom permalinks for pages and posts?
  5. How does Jekyll integrate with GitHub Pages for deployment?

Challenge: Build a Jekyll portfolio site with a blog section, a projects collection, custom layouts, data-driven team page, and deploy it to GitHub Pages.

FAQ

Do I need Ruby installed to use Jekyll?

Yes. Jekyll is a Ruby gem. You need Ruby 2.7+ and Bundler. GitHub Pages runs Jekyll on their servers, so you only need Ruby for local development.

Can Jekyll handle thousands of pages?

Yes. Jekyll is mature and stable for large sites. Build time may increase with many pages, but it scales reasonably for mid-sized content sites.

How does Jekyll compare to Hugo?

Jekyll is simpler for beginners but slower to build. Hugo is much faster (Go vs Ruby) and has a more powerful template system. Jekyll wins on GitHub Pages integration.

Can I use React or Vue with Jekyll?

Not natively. Jekyll outputs static HTML. You can embed JavaScript frameworks in specific pages, but Jekyll itself doesn't support component-based rendering.

Does Jekyll support incremental builds?

Jekyll 4.0+ supports incremental builds with --incremental flag. It only rebuilds changed files, significantly speeding up development iterations.

Mini Project

Create a Jekyll blog with 5 posts across 3 categories, custom layouts for posts and pages, a team data file with Liquid-driven display, tag pages with automatic listing, and deploy to GitHub Pages using the built-in Jekyll Builder.

What's Next

You've built a Jekyll site. Now explore 11ty (Eleventy) — a simpler JavaScript-based SSG that offers flexibility without framework lock-in.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro