Tech Blog

Building and Maintaining This Blog - Jekyll & GitHub Pages

Table of Contents

How this website started (November 23, 2022)

After tried the templates from HTML5UP and got confused with most of the fancy css settings, I gave up on writing progress with my learning very quickly.

Then I got inspired by two blogs and decided to build a new one. One is Andrej Karpathy’s website, where he mentioned not using heavy frameworks and just focusing on the content. Then I learned how to use Jekyll to generate everything, especially since it supports Markdown. Another was when I tried to use WeChat in docker, I came across Lei Mao’s blog and got inspired. His blog is so inclusive, from his research, work, and personal life. I think his content was amazing, it was so enjoyable to read, and I want to do something similar.

Thanks to Tim and his fantastic tutorial on how to build a website with Jekyll. Here is his Youtube video and Doc that is super helpful. Following his tutorial and working on Ubuntu 20.04 with no issues.

Image popups with Magnific Popup (September 9, 2023)

While I am building a documentation website for my work, I decided to use the free template just-the-docs as a quick solution. However, this theme doesn’t have an image pop-up feature: when you click on the image, it would pop into a larger version, make it easier for readers to see the details of the sample images. For example, when you click the image below, it pops up.

Therefore, in this section, I will show you what I did to simply include the Magnific Popup plugin in this project. Specifically, for the just-the-docs theme.

Step 1: Install Magnific Popup

You can go to the Magnific Popup’s GitHub repository, follow the instruction there.

The magnific-popup-rails gem is for Rails. For Jekyll, use the CSS and JS files as described below.

Step 2: Add the Magnific Popup files to your Jekyll site

You will need to add the Magnific Popup’s main CSS (magnific-popup.css) and JS (jquery.magnific-popup.js) files to your Just-The-Docs repository. Both files are in the /dist folder in the Magnific Popup’s GitHub repository.

  1. Create a new folder in your repository root directory named /assets.
  2. Inside assets, create two more folders: /css and /js.
  3. Upload magnific-popup.css into the /assets/css folder and jquery.magnific-popup.min.js into the /assets/js folder.

You might ask: why .min.js file not using the .js file?

This reason is: [from ChatGPT 4.0]

  • The .min.js files are minified versions of regular JavaScript .js files.
  • Minification is the process of removing all unnecessary characters from the source codes without changing their functionality. These unnecessary characters usually include white spaces, new line characters, comments, and sometimes block delimiters, which are used to add readability to the code but are not required for execution.

Step 3: Override the theme’s default layout

You will need to override Just-The-Docs’ default layout to include references to the CSS and JS files. You can do this in the _layouts directory.

  1. In your own repository, create a new folder at the root named _layouts if it’s not there.
  2. Inside _layouts, create a new file and name it default.html.
  3. Go to Just-The-Docs theme repository on GitHub.
  4. Find the _layouts directory in the Just-The-Docs theme repository, then find the default.html file.
  5. Copy all the content of default.html from the github repo to your own /_layouts/default.html.

Step 4: Include references to Magnific Popup in your template

Now that your default.html is created, you need to include CSS and JS files.

In default.html, insert this inside the existing <head> section:

1
<link rel="stylesheet" href="{{ "/assets/css/magnific-popup.css" | relative_url }}">

Then, scroll to the end of the document and just before the </body> end tag, insert these two lines:

1
2
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="{{ "/assets/js/jquery.magnific-popup.min.js" | relative_url }}"></script>

Step 5: Initialize the plugin

You can either initialize the plugin in the default.html itself or create a new .js file

  1. Create a new main.js file in the /assets/js directory.
  2. In the main.js file, add the following JavaScript:
    1
    2
    3
    
    $(document).ready(function() {
     $('.image-link').magnificPopup({type:'image'});
      });
    
  3. Add this main.js file into your default.html, just after the previous script link:
1
2
3
4
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="{{ "/assets/js/jquery.magnific-popup.min.js" | relative_url }}"></script>
<!-- Add it here -->
<script src="{{ "/assets/js/main.js" | relative_url }}"></script>

Step 6: Test with your image

You can use raw HTML in your Markdown file like below:

1
2
3
<a class="image-link" href="pathToYourLargeImage">
  <img src="pathToYourThumbnailImage" alt="Image Description">
</a>

And that’s it, enjoy the new feature!

Jekyll and GitHub Pages (January 18, 2025)

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 learned 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
  1. 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
      
  2. 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

  1. 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
    
  2. 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
  1. 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.
  2. 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.

  1. First, install the desired Ruby version: ruby-install 3.2.3.
  2. 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.

  3. 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.

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:

  1. Go to your repository’s Settings tab.
  2. Find the Pages section.
  3. Under the Build and deployment section, set the source to GitHub Actions.
  4. 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!

New layout with AI (October 17, 2026)

AI has come far enough that I can redesign this blog without being a CSS expert. Still the “500-pound website” analogy has stuck with me, so I’ve tried to keep this blog as minimal as possible. It now uses custom layouts instead of a prebuilt theme, though it still relies on Jekyll and a few external libraries. I have full control over the design, or perhaps Codex does. Either way, I’m very happy with how it has turned out.