Understand Jekyll and GitHub Pages
I’ve been using Jekyll to build websites for both work and my personal site (this one) for years, but I never took the time to fully understand how it works. In this post, I’m diving into everything I want to know—and need to know—about building a website with Jekyll and GitHub Pages.
Intro
What is Jekyll?
- Jekyll is a static site generator written in Ruby. It takes plain text content (usually written in Markdown or HTML) and combines it with layouts to create a complete static website. It’s a popular choice for people building personal or professional websites.
What is Ruby?
- Ruby is a programming language, best known for the Ruby on Rails framework.
What is RubyGems?
- RubyGems is Ruby’s package manager. It helps developers distribute, manage, and install libraries (called “gems”) for Ruby projects. Jekyll itself is a Ruby gem. Think of RubyGems as the Ruby equivalent of Python’s pip.
What is a Gem?
- A gem is a Ruby library or package, distributed via RubyGems.org. You can install gems using the
gem
command or Bundler.
What is Bundler? And when do we use it?
- Bundler is a Ruby tool for managing gem dependencies in your project. It ensures the gems listed in a Gemfile are installed in the correct versions and loaded properly.
- Key Commands:
bundle install
: Installs all gems specified in the Gemfile.bundle exec
: Executes commands in the context of the installed gems (e.g.,bundle exec jekyll serve
).
What are Gemfile and Gemfile.lock?
- Gemfile: A file listing the Ruby gems your project depends on, along with their required versions.
- Gemfile.lock: Automatically generated by Bundler when you run bundle install. It locks the exact versions of gems used.
Do not add Gemfile.lock to your .gitignore. Including it ensures that others cloning your repository will install the exact same gem versions, making the project behave consistently across environments.
What’s the relationship between gem
and Bundler (bundle
)?
gem
: Provided by RubyGems, this is the core command for installing and managing gems system-wide.- Bundler: Works on top of RubyGems. It introduces the Gemfile and Gemfile.lock to define and lock gem versions for a project, ensuring isolated environments.
- Bundler with Gemfile is similar to Conda with requirements.txt. Both tools ensure consistent dependency management across environments.
Get Started
1. Find a Theme You Like
If you’re looking to build a blog but don’t know where to start, there are tons of free themes available online. You can find some great ones on the jekyll website. For my site, I’m using the Chirpy theme.
Most themes include instructions and a ready-to-use template. For example, Chirpy has a detailed getting-started guide. It’s all hosted on GitHub, so setting it up is as simple as clicking through a few buttons in their instructions. After that, you’ll clone the repository to your local machine and host it locally to write your first blog post. Here’s where things start to get a bit trickier.
2. Setting the environment
Here I will include both Ubuntu and macOS (M2) since I use both.
Ubuntu
- Follow the official Ubuntu installation guide. By the end, you’ll have two key gems installed: Jekyll and Bundler.
- Following the commands from the official guide, the gems will be stored in your home direcotry under a folder called
gems
, which in my opinion, annoying. I prefer to create a dedicated folder, “jekyll_ws”, for better organization. Here’s how I set it up:1 2 3 4
echo '# Install Ruby Gems to ~/jekyll_ws/gems' >> ~/.bashrc echo 'export GEM_HOME="$HOME/jekyll_ws/gems"' >> ~/.bashrc echo 'export PATH="$HOME/jekyll_ws/gems/bin:$PATH"' >> ~/.bashrc source ~/.bashrc
- Following the commands from the official guide, the gems will be stored in your home direcotry under a folder called
- Navigate to the root directory of your cloned repository and run:
bundle install
. Bundler will install all the dependencies listed in the Gemfile. If everything works, you can host your site locally by running:bundle exec jekyll serve
. Then, visit your site at http://127.0.0.1:4000/.
Troubleshooting Version Errors
If you encounter errors like this:
1
2
3
4
5
6
7
8
9
10
$ bundle update
Fetching gem metadata from https://rubygems.org/...........
Resolving dependencies...
Bundler found conflicting requirements for the Ruby version:
In Gemfile:
html-proofer (~> 5.0) was resolved to 5.0.9, which depends on
Ruby (< 4.0, >= 3.1)
Current Ruby version:
Ruby (= 3.0.2)
This means your Ruby version is too old (e.g., you have 3.0.2, but it requires 3.1 or higher). Unfortunately, you can’t update Ruby using apt because its version is outdated. You’ll need a version manager like rbenv.
How to use rbenv to install Ruby
- Avoid using
sudo apt install rbenv
—it’s outdated. Instead, install rbenv it using Git:1 2 3
git clone https://github.com/rbenv/rbenv.git ~/.rbenv ~/.rbenv/bin/rbenv init # then restart the terminal
- With rbenv installed, you can install Ruby:
1 2 3 4 5 6 7 8 9
# list latest stable versions: rbenv install -l # install a Ruby version: rbenv install 3.1.2 rbenv global 3.1.2 # set the default Ruby version for this machine # or: rbenv local 3.1.2 # set the Ruby version for this directory
Once that’s done, try running bundle install
again. If no errors occur, you’re ready to use: bundle exec jekyll serve
and visit your local host website.
MacOS
- Follow the macOS installation guide. This guide explains why you shouldn’t use the pre-installed system Ruby and provides commands for installing a newer Ruby version and version management tools.
- For more detailed instructions, check out this guide, which covers potential issues and their solutions.
- Once Ruby is set up, navigate to the root directory of your cloned repository and run:
bundle install
. Bundler will install all the dependencies listed in the Gemfile. If everything works, you can host your site locally by running:bundle exec jekyll serve
. Then, visit your site at http://127.0.0.1:4000/.
Handling Version Issues with chruby
If you encounter errors like this:
1
2
3
4
5
6
7
8
9
10
$ bundle update
Fetching gem metadata from https://rubygems.org/...........
Resolving dependencies...
Bundler found conflicting requirements for the Ruby version:
In Gemfile:
html-proofer (~> 5.0) was resolved to 5.0.9, which depends on
Ruby (< 4.0, >= 3.1)
Current Ruby version:
Ruby (= 3.0.2)
use chruby, a version manager.
- First, install the desired Ruby version:
ruby-install 3.2.3
. Then, switch between Ruby versions by typing:
chruby
. This will list available versions:1 2 3
$ chruby ruby-3.2.3 * ruby-3.3.5
so you know that you are currently using 3.3.5, and 3.2.3 is available to switch to.
- To switch to a specific version, run:
chruby 3.2.3
Now you’re all set! Try running bundle exec jekyll serve and visit your local site to start building your blog.
3. How to Publish on GitHub
What is GitHub Pages?
- GitHub Pages is a free web hosting service provided by GitHub. It allows you to host static websites directly from a repository, making it a great option for personal or project pages.
What is GitHub Actions?
- GitHub Actions is a CI/CD (Continuous Integration/Continuous Deployment) tool that automates workflows in your GitHub repository.
- Workflows are defined in YAML files located in the
.github/workflows/
directory. These workflows can be triggered by events like pushing changes to your repository.
- Workflows are defined in YAML files located in the
For example, if you’re using a GitHub-hosted theme like Chirpy, they’ve already set up the necessary yaml file for you. This means every time you push changes to your repository, the workflow automatically builds and deploys your website.
How to Deploy Using GitHub Actions:
- Go to your repository’s Settings tab.
- Find the Pages section.
- Under the Build and deployment section, set the source to GitHub Actions.
- Push your changes to the repository.
After pushing, go to the Actions tab to check if the deployment workflow was successful. Once completed, your website will be live!
Creating a static website for personal use is easier than you might think, especially with such a vibrant community. I hope this post has been helpful—happy writing!