Jekyll
Ruby-based SSG standard for GitHub Pages. Over 49k GitHub stars, ideal for simple blogs and documentation sites.
トレンド・動向
Maintains strong popularity for personal projects and open source documentation due to full GitHub Pages integration.
# Static Site Generator
Jekyll
## Overview
Jekyll is a "blog-aware static site generator" built with Ruby, released in 2008 as one of the most established and proven SSGs available. With over 49k GitHub stars, it serves as the standard engine for GitHub Pages, offering complete integration for free site hosting. Through simple Markdown and Liquid templating, rich plugin ecosystem, and file-based CMS-like management, Jekyll powers everything from personal blogs to enterprise websites with reliability and ease.
## Details
Jekyll 2025 edition maintains its pioneering position in the static site generator landscape, particularly gaining massive developer community support through complete GitHub Pages integration. Leveraging Ruby's mature development ecosystem, it provides flexible content processing through the Liquid template engine, metadata management via YAML front matter, and extensive functionality through its rich plugin library. It generates complete static websites from Markdown, HTML, CSS, and JavaScript files, achieving high performance and security.
### Key Features
- **Complete GitHub Pages Integration**: Standard engine with free hosting and automatic deployment
- **Blog-Oriented Design**: Permalinks, categories, posts, and custom layouts as first-class features
- **Liquid Templates**: Dynamic content generation and flexible template processing
- **Rich Plugin Ecosystem**: Functionality extension through Ruby Gems
- **File-based CMS**: Database-free file-based management
- **Advanced Customization**: Layout, includes, and SASS support
## Pros and Cons
### Pros
- Complete GitHub Pages integration for free hosting and automatic deployment
- 17 years of development track record with mature ecosystem and abundant learning resources
- Rich plugin library enabling advanced functionality extension and customization
- Intuitive content management with simple Markdown + YAML
- Large community support and theme variety
- Proven enterprise and open source project adoption with reliability
### Cons
- Ruby environment required, adding complexity to local development setup
- Build speed for large sites inferior compared to Hugo or Zola
- Plugin restrictions in GitHub Pages safe mode
- Limited integration with modern JavaScript/TypeScript ecosystems
- Ruby dependency complicates CI/CD environment configuration
- Slower adaptation to latest web development trends
## Reference Pages
- [Jekyll Official Site](https://jekyllrb.com/)
- [Jekyll GitHub Repository](https://github.com/jekyll/jekyll)
- [GitHub Pages Documentation](https://docs.github.com/pages/)
## Code Examples
### Installation and Setup
```bash
# Install Ruby and dependencies (Ubuntu)
sudo apt-get install ruby-full build-essential zlib1g-dev
# Configure user Gem settings
echo '# Install Ruby Gems to ~/gems' >> ~/.bashrc
echo 'export GEM_HOME="$HOME/gems"' >> ~/.bashrc
echo 'export PATH="$HOME/gems/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
# Install Jekyll and Bundler
gem install jekyll bundler
# Create new site
jekyll new my-awesome-site
cd my-awesome-site
# Check Gemfile
cat Gemfile
# Install dependencies
bundle install
# Start local development server
bundle exec jekyll serve
# => Available at http://localhost:4000
# GitHub Pages compatibility check
bundle exec jekyll serve --baseurl=""
```
### Basic Configuration and Site Structure
```yaml
# _config.yml - Basic configuration
title: My Jekyll Website
email: [email protected]
description: >-
A simple and beautiful Jekyll site.
Perfect for blogs and technical documentation.
baseurl: "" # Subpath (e.g., /blog)
url: "https://username.github.io" # Base URL
# Build settings
markdown: kramdown
highlighter: rouge
theme: minima
# Plugin configuration
plugins:
- jekyll-feed
- jekyll-sitemap
- jekyll-seo-tag
# Exclude files
exclude:
- Gemfile
- Gemfile.lock
- node_modules
- vendor/bundle/
- vendor/cache/
- vendor/gems/
- vendor/ruby/
# Collections configuration
collections:
projects:
output: true
permalink: /:collection/:name/
# Default settings
defaults:
- scope:
path: ""
type: "posts"
values:
layout: "post"
author: "Your Name"
- scope:
path: ""
type: "pages"
values:
layout: "page"
```
### Creating Posts and Pages
```markdown
---
# _posts/2025-01-15-jekyll-tutorial.md
layout: post
title: "Jekyll Getting Started Guide"
date: 2025-01-15 10:00:00 +0000
categories: [tutorial, jekyll]
tags: [static-site, github-pages, ruby]
author: "Your Name"
excerpt: "Learn how to build websites with Jekyll."
---
# Jekyll Getting Started Guide
Jekyll is a Ruby-based static site generator.
## Features
- Complete GitHub Pages integration
- Markdown + Liquid templates
- Rich plugin ecosystem
## Code Example
```ruby
# Gemfile
source "https://rubygems.org"
gem "jekyll", "~> 4.2.0"
gem "minima", "~> 2.5"
group :jekyll_plugins do
gem "jekyll-feed", "~> 0.12"
gem "jekyll-sitemap"
gem "jekyll-seo-tag"
end
```
## Summary
Using Jekyll, you can build simple and fast websites.
---
# pages/about.md
---
layout: page
title: About
permalink: /about/
---
This is the About page.
You can include company information or personal profiles.
## Contact
- Email: {{ site.email }}
- GitHub: [username](https://github.com/username)
```
### Layouts and Templates
```html
<!-- _layouts/default.html -->
<!DOCTYPE html>
<html lang="{{ page.lang | default: site.lang | default: 'en' }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ page.title }} | {{ site.title }}</title>
<meta name="description" content="{{ page.excerpt | default: site.description | strip_html | normalize_whitespace | truncate: 160 | escape }}">
<link rel="stylesheet" href="{{ '/assets/main.css' | relative_url }}">
<link rel="canonical" href="{{ page.url | replace:'index.html','' | absolute_url }}">
{% feed_meta %}
{% seo %}
</head>
<body>
<header class="site-header" role="banner">
<div class="wrapper">
<a class="site-title" href="{{ '/' | relative_url }}">{{ site.title | escape }}</a>
<nav class="site-nav">
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger">
<span class="menu-icon">
<svg viewBox="0 0 18 15" width="18px" height="15px">
<path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
</svg>
</span>
</label>
<div class="trigger">
{% for my_page in site.pages %}
{% if my_page.title %}
<a class="page-link" href="{{ my_page.url | relative_url }}">{{ my_page.title | escape }}</a>
{% endif %}
{% endfor %}
</div>
</nav>
</div>
</header>
<main class="page-content" aria-label="Content">
<div class="wrapper">
{{ content }}
</div>
</main>
<footer class="site-footer h-card">
<div class="wrapper">
<div class="footer-col-wrapper">
<div class="footer-col footer-col-1">
<ul class="contact-list">
<li class="p-name">{{ site.title | escape }}</li>
{% if site.email %}
<li><a class="u-email" href="mailto:{{ site.email }}">{{ site.email }}</a></li>
{% endif %}
</ul>
</div>
<div class="footer-col footer-col-2">
{% include social.html %}
</div>
<div class="footer-col footer-col-3">
<p>{{ site.description | escape }}</p>
</div>
</div>
</div>
</footer>
</body>
</html>
<!-- _layouts/post.html -->
---
layout: default
---
<article class="post h-entry" itemscope itemtype="http://schema.org/BlogPosting">
<header class="post-header">
<h1 class="post-title p-name" itemprop="name headline">{{ page.title | escape }}</h1>
<p class="post-meta">
<time class="dt-published" datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">
{{ page.date | date: "%B %d, %Y" }}
</time>
{% if page.author %}
<span itemprop="author" itemscope itemtype="http://schema.org/Person">
<span class="p-author h-card" itemprop="name">{{ page.author }}</span>
</span>
{% endif %}
</p>
</header>
<div class="post-content e-content" itemprop="articleBody">
{{ content }}
</div>
{% if site.disqus.shortname %}
{% include disqus_comments.html %}
{% endif %}
<a class="u-url" href="{{ page.url | relative_url }}" hidden></a>
</article>
```
### Plugin Configuration and Extensions
```ruby
# Gemfile - Plugin configuration
source "https://rubygems.org"
gem "jekyll", "~> 4.2.0"
# Theme
gem "minima", "~> 2.5"
# GitHub Pages compatibility
gem "github-pages", group: :jekyll_plugins
group :jekyll_plugins do
gem "jekyll-feed", "~> 0.12" # RSS feed generation
gem "jekyll-sitemap" # Sitemap generation
gem "jekyll-seo-tag" # SEO meta tags
gem "jekyll-gist" # Gist embedding
gem "jekyll-paginate" # Pagination
gem "jekyll-archives" # Archive pages
gem "jekyll-redirect-from" # Redirect configuration
gem "jekyll-admin" # Admin interface (development)
end
```
```yaml
# _config.yml - Plugin detailed configuration
plugins:
- jekyll-feed
- jekyll-sitemap
- jekyll-seo-tag
- jekyll-gist
- jekyll-paginate
- jekyll-archives
- jekyll-redirect-from
# Pagination settings
paginate: 5
paginate_path: "/blog/page:num/"
# Archive settings
jekyll-archives:
enabled:
- categories
- tags
- year
- month
layout: archive
permalinks:
year: '/:year/'
month: '/:year/:month/'
day: '/:year/:month/:day/'
tag: '/tag/:name/'
category: '/category/:name/'
# SEO settings
title: My Jekyll Site
description: Awesome Jekyll powered website
url: "https://username.github.io"
author:
name: Your Name
email: [email protected]
twitter: username
social:
name: Your Name
links:
- https://twitter.com/username
- https://github.com/username
- https://linkedin.com/in/username
```
### Advanced Features and Customization
```yaml
# _config.yml - Advanced configuration
# Collections definition
collections:
projects:
output: true
permalink: /:collection/:name/
team:
output: false
# Default values
defaults:
- scope:
path: ""
type: "posts"
values:
layout: "post"
author: "default-author"
show_excerpts: true
- scope:
path: "projects"
type: "projects"
values:
layout: "project"
- scope:
path: ""
type: "pages"
values:
layout: "page"
# Sass settings
sass:
sass_dir: _sass
style: compressed
# Kramdown settings
kramdown:
input: GFM
syntax_highlighter: rouge
syntax_highlighter_opts:
css_class: 'highlight'
span:
line_numbers: false
block:
line_numbers: true
# Exclude settings
exclude:
- Gemfile
- Gemfile.lock
- node_modules
- vendor/
- .sass-cache/
- .jekyll-cache/
- gemfiles/
- README.md
- package.json
- package-lock.json
```
```liquid
<!-- _includes/navigation.html -->
<nav class="main-nav">
<ul>
<li><a href="{{ '/' | relative_url }}"
{% if page.url == '/' %}class="current"{% endif %}>Home</a></li>
<li><a href="{{ '/blog/' | relative_url }}"
{% if page.url contains '/blog/' %}class="current"{% endif %}>Blog</a></li>
<li><a href="{{ '/projects/' | relative_url }}"
{% if page.url contains '/projects/' %}class="current"{% endif %}>Projects</a></li>
<li><a href="{{ '/about/' | relative_url }}"
{% if page.url == '/about/' %}class="current"{% endif %}>About</a></li>
</ul>
</nav>
<!-- Custom Liquid filter examples -->
{% assign sorted_posts = site.posts | sort: 'date' | reverse %}
{% for post in sorted_posts limit:5 %}
<article>
<h3><a href="{{ post.url | relative_url }}">{{ post.title }}</a></h3>
<time>{{ post.date | date: "%B %d, %Y" }}</time>
<p>{{ post.excerpt | strip_html | truncate: 150 }}</p>
</article>
{% endfor %}
<!-- Conditional statements and data access -->
{% if site.data.team %}
<section class="team">
<h2>Team Members</h2>
{% for member in site.data.team %}
<div class="member">
<h3>{{ member.name }}</h3>
<p>{{ member.role }}</p>
{% if member.bio %}
<p>{{ member.bio }}</p>
{% endif %}
</div>
{% endfor %}
</section>
{% endif %}
```
### GitHub Pages Production Deployment
```yaml
# .github/workflows/jekyll.yml - GitHub Actions
name: Build and deploy Jekyll site to GitHub Pages
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.1'
bundler-cache: true
cache-version: 0
- name: Setup Pages
id: pages
uses: actions/configure-pages@v3
- name: Build with Jekyll
run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}"
env:
JEKYLL_ENV: production
- name: Upload artifact
uses: actions/upload-pages-artifact@v2
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
```
```bash
# Production build and deployment
# 1. Local production environment testing
JEKYLL_ENV=production bundle exec jekyll build
bundle exec jekyll serve --baseurl="" # For GitHub Pages Project
# 2. Manual deployment (custom server)
JEKYLL_ENV=production bundle exec jekyll build
rsync -avz --delete _site/ [email protected]:/var/www/html/
# 3. Docker environment build
docker run --rm -v $(pwd):/srv/jekyll jekyll/jekyll:latest jekyll build
# 4. Build result verification
ls -la _site/
find _site -name "*.html" | head -10
```