As a computer science student, I often want to record my learning notes and experiences in blog posts for sharing, as well as for my own reference. However, all of my previous countless attempts to build a blog ended up in failure. I just couldn’t persist in maintaining them mainly for two reasons: either I used free blog platforms such as CSDN and Zhihu, and their limits and poor UI designs deterred me from writing posts frequently. Or I tried to build a blog space from scratch with a rented server and got distracted by cumbersome coding in HTML/CSS and JavaScript.

A few days ago, one of my friends started writing a GitBook, which intrigued my interest in writing blog posts again. Having learned from previous failures, I came up with a list of requirements for the blog platform to be used this time:

  1. Minimum cost. Avoid dedicated servers;
  2. Maximum freedom. Allow me to customize UI and functionalities;
  3. Minimum details. Avoid complicated site management so that I can concentrate on creating contents.

After some research, I found that the combination of Jekyll and GitHub Pages perfectly suits my needs.

GitHub Pages


GitHub Pages is a static-site hosting service provided by GitHub, intending to help projects and organizations on GitHub build doc sites.1 It is very simple to use GitHub Pages to build a website. All you need to do is to create a repository named as <username> (where <username> is your GitHub username), and the files in this repo will be automatically published on https://<username> by GitHub.2

For example, let’s create a file index.html

<!-- index.html -->
<!DOCTYPE html>
    <title>Hello GitHub Pages!</title>
    <h1>Hello GitHub Pages!</h1>
    <p>This page is hosted on GitHub Pages.</p>

And push to the <username> repo that we just created. Now access https://<username> in your web browser and we can see the web page immediately:

Example webpage

As you can see, GitHub Pages manages all the trivial details of website servers. We can rest ourselves and write frontend web pages to build a static website. The use of this service does come with several limits. For example the size of the website cannot exceed 1 GB; there is a soft bandwidth limit of 100 GB per month etc.3 Of course illegal uses and contents prohibited by the terms of service are not allowed. It is also mentioned that GitHub Pages is not intended for or allowed to run business or other commercial websites etc. However, it is good enough for our purpose of building a personal blog.

In summary, GitHub Pages provides us with free hosting space for a static website and a free domain name. We can use git to manage our contents and publish the website easily with a push to the GitHub repo. If wanted, we can also use custom domain names.4 However, despite all the benefits, we still need to implement the whole frontend by ourselves. It will be a massive amount of work if we want a beautiful user interface (been there, tried that, gave up :smiley:). Furthermore, every post must be written as a complete web page using HTML, which violates our intention to separate content creation and website management. To this end, we need Jekyll to our rescue.



Jekyll is a static-site generator with templates and support for markup languages. This is a typical structure for a Jekyll project:

├── 404.html                          # Custom 404 page
├── _config.yml                       # Jekyll configuration file
├── _data                             # Data files
├── _includes                         # Include files
├── index.html                        # Index page
├── _layouts                          # Layout templates
│   ├── default.html                  # Default template
│   └── post.html                     # Post page template
├── _drafts                           # Drafts
│   └──   # Unpublished draft
└── _posts                            # Posts
    └──     # Published post

We can think of Jekyll as a “compiler” that takes in contents written in markup languages (Markdown, HTML, etc), and outputs a static website. It converts our posts (for example _posts/ into corresponding web pages according to predefined layouts. Then all pages are organized in the website structure. This makes our life much simpler because Markdown is easier to write than HTML. If you don’t know Markdown, it is definitely worth learning.5 The use of page layout templates also nicely isolates contents from formats by reusing codes. We only need to write templates in HTML/CSS once, and focus on writing posts that adopt those templates later. The following is an example of a layout template:

<!-- _layouts/default.html -->
<!DOCTYPE html>
    <title>{{ page.title }}</title>
    <div class="page-content">
      {{ content }}

This simple layout file describes an HTML page. The double braces {{ }} in the layout file is the Liquid template language used by Jekyll (for more info please refer to the official docs6). Now if we write another file that uses this layout:

layout: default
title: 'Hello Jekyll!'

## Hello Jekyll!

This page uses the default layout.

Then Jekyll will generate a corresponding HTML file:

<!-- hello-jekyll.html -->
<!DOCTYPE html>
    <title>Hello Jekyll!</title>
    <div class="page-content">
      <h2 id="hello-jekyll">Hello Jekyll!</h2>
      <p>This page uses the default layout.</p>

The README file of Jekyll introduces its philosophy, which I think is very close to our requirements mentioned above:

Jekyll does what you tell it to do – no more, no less. It doesn’t try to outsmart users by making bold assumptions, nor does it burden them with needless complexity and configuration. Put simply, Jekyll gets out of your way and allows you to concentrate on what truly matters: your content.

To make things even better, GitHub Pages uses Jekyll as its pre-process engine. Every file we upload to the GitHub Pages repo will be automatically processed by Jekyll before it is published. 7 One thing to note, the Jekyll used by GitHub Pages does not behave exactly the same as the ones installed locally on our computers. For example, custom plugins are not allowed on GitHub Pages for security reasons. 8 There is a list of allowd plugins that you can use though.9

Install Jekyll locally

When developing the website or writing posts, we may want to check live results on our local machines. This section briefly introduces how to use Jekyll locally (using Ubuntu).

First of all, Jekyll is written in Ruby, therefore we need to install the runtime for Ruby and the package manager, RubyGem:

 sudo apt update
 sudo apt install ruby-full
 sudo apt install gem
 sudo gem update --system

Then install Jekyll and Bundler via RubyGem:

 sudo gem install jekyll bundler

After successful installation, we can use Jekyll to create a new blog:

 jekyll new myblog

This command will initialize a basic Jekyll project under ./myblog/:

├── 404.html
├── _config.yml
├── Gemfile
├── Gemfile.lock
└── _posts
    └── 2019-01-21-welcome-to-jekyll.markdown

We can build and host the website with Jekyll in ./myblog/. Run

 cd myblog
 bundle exec jekyll serve

and access localhost:4000 in your web browser, then you should be able to see the website.


If you are new to Jekyll, you can read the official docs10 and try some of the features in this basic project. You may push the project to the GitHub Pages repo created earlier to publish the website.

Use existing themes

If you don’t even bother writing the templates and styles on your own, you can always find many high-quality open-source themes online. For example on or This blog you are currently viewing is modified from a great theme Centrarium. Since I have made many modifications and added some other functionalities, I also published my theme on GitHub: Jekyll-Theme-HW311. If you like this theme or want to use it, you are welcomed to fork and star it. The main features include (including original features from Centrarium):

  • In-site searching
  • Basic support for multilanguage without plugins (GitHub Pages friendly)
  • Easily customizable fonts and colors
  • Cover images for your homepage and blog posts
  • Archiving of posts by categories
  • Syntax highlighting for code snippets
  • Disqus integration for post comments
  • Lightbox for viewing full-screen photos and albums
  • Google Analytics with custom page name tracking
  • Social media integration (Twitter, Facebook, LinkedIn, GitHub, and more)

To use this theme, fork it on GitHub and rename it to <username> (substitute <username> with your GitHub username).

Before using this theme, you also need to edit _config.yml to configure the blog to your settings. Entries that needs configuring are:

title: '<website title>'
subtitle: '<website subtitle>'
email: '<your email>'
name: '<your name>'
description: '<website description>'
url: '<website url>'                  # e.g. https://<username>
cover: '<path to cover image>'
logo: '<path to logo>'
disqus_shortname: '<disqus shortname>'
ga_tracking_id: '<ga tracking id>'
  - ...                               # Social networks and sharing settings
  ...                                 # OS protocol settings

After configuring these settings and pushing to GitHub, you can now view your own blog on <username>! :tada:

To write posts, create YYYY-MM-DD-<post-title>.md files under en/_posts or zh/_posts. You may find some examples to start with there.

Data files such as multilanguage settings, translations, and post categories etc can by found under _data/.

Please refer to Jekyll’s official docs10 for usage of Jekyll’s features. If you have specific questions about this theme, please leave comments below or in the GitHub repo.

Use a custom domain name

If you don’t like the domain name provided by GitHub, you can purchase your own domain name and use it for your GitHub Page. Please check the tutorial provided by GitHub. 4

First, configure the custom domain name in your GitHub Pages repo. You can add a domain name record via either Settings -> GitHub Pages -> Custom domain; or directly create a CNAME file containing your domain name (without protocol name, for example, but not under the project root directory.

Then configure A records with your DNS provider. Set the IP addresses to the following:11

These IP addresses were obtained from the GitHub Pages official docs11 at the time this post was written. Please check again when configuring.


By now, we have built a personal blog using Jekyll and GitHub. This solution may have some shortages, for example we can only build static websites; plugins are limited by GitHub Pages etc., it fits our requirements nevertheless. If you want to focus on writing posts, you can start right away using templates and layouts. If you are also interested in tweaking the website and developing new features like me, hopefully this post and its references may come to your help.

And hopefully I can keep on going this time. (laugh)