Jekyll Tutorial
Jekyll converts markdown files to html; helps to generate blogs in a minimalistic style. This blog provides a quick start for installation, configuration, and simple usage.
Installation
Before you can use Jekyll to create a GitHub Pages site, you must install Jekyll and Git. Follow the instruction in the websites below:
https://jekyllrb.com/docs/ruby-101/
Which shell am I using?
Starting with macOS Catalina (10.15), Apple set the default shell to the Z shell (zsh). In previous macOS versions, the default was Bash.
-
In
zsh
, the configuration file is~/.zshrc
. -
In
bash
, it’s~/.bash_profile
.
Every time you make changes with the configuration file
-
run
source ~/.bash_profile
if you havebash
. [✘] -
run
source ~/.zshrc
if the shell iszsh
. [✔]
After having installed ruby, run ruby -v
to check ruby version.
A Gemfile
is a list of gems used by your site. Every Jekyll site has a Gemfile in the main folder.
-
Create a
Gemfile
in the root. The file should be called ‘Gemfile’ and should not have any extension. You can create a Gemfile with Bundler and then add thejekyll
gem:bundle init bundle add jekyll
-
Manage plugins
-
add plugins to your
Gemfile
source 'https://rubygems.org' gem 'jekyll' group :jekyll_plugins do gem 'jekyll-sitemap' gem 'jekyll-feed' gem 'jekyll-seo-tag' end
-
add plugins to
_config.yml
plugins: - jekyll-feed - jekyll-sitemap - jekyll-seo-tag
-
install them by running
bundle update
-
Gemfile syntax
~>
Pessimistically greater than or equal to
gem "devise", "~> 3.1" # same as >= 3.1.0 and < 4.0.0
Q: What is a Gemfile.lock
?
A: Gemfile.lock file contains all the information about the gems that are currently installed. This file is created automatically after we run the bundle install
command. A Gemfile.lock
has a list of the exact versions of the gems required for the application.
Bundler
is a gem that installs all gems in your Gemfile
. Gem manager. Commands start with bundle <>
.
-
Install Bundler using
gem install bundler
. You only need to install it once, not every time you create a new Jekyll project. -
To install gems in your Gemfile using Bundler and serve the website, run the following in the directory that has the Gemfile:
bundle install # install gem dependencies for the project bundle exec jekyll serve # serve the website, run the site locally
Now you can navigate to
http://localhost:4000
to preview your site.Jekyll rebuilds automatically after each change.
-
All of the normal Jekyll commands are available to you, but you should prefix them with
bundle exec
so that Bundler runs the version of Jekyll that is installed in your project folder. -
bundle add webrick
Add gem to the Gemfile and run bundle install. -
help page
bundle add --help
Jekyll file structure
Workflow of software develoment:
coding $\rightarrow$ build $\rightarrow$ deploy $\rightarrow$ test $\rightarrow$ release
Deploying
Deploying is taking website content and publishing it to the Internet. Technically speaking, it is the process of compiling, or building, your code and hosting the JavaScript, CSS, and HTML on a web server. After deployment, you will always have your live website, which is called the live environment or production environment.
Development
If you want the ability to make changes without these affecting your live website, then you can add additional environments. These environments are called development environments or deployment environments.
https://jekyllrb.com/docs/structure/
https://nicolas-van.github.io/easy-markdown-to-github-pages/
.
|-- _config.yml
|-- _includes
|-- _layouts
| |-- default.html
| |-- post.html
|-- _posts
| |-- 2007-10-29-why-every-programmer-should-play-nethack.textile
| |-- 2009-04-26-barcamp-boston-4-roundup.textile
├── _sass
│ ├── _base.scss
│ └── _layout.scss
|-- _site
|-- index.html # => http://example.com/
|-- about.md # => http://example.com/about.html
|-- contact.html # => http://example.com/contact.html
-
_config.yml
Configuration file, put in the root directory of your site.- set global variables; configure plugins;
-
index.md
The index page of your website can be aindex.md
file or aREADME.md
file. If both exists theindex.md
file has priority. -
_includes
Contains snippets of code that can be inserted in multiple layouts within the same theme-gem.页面的共有部分,可以存储成一个单独的文件。这样设计可以方便以后的维护。而这个单独的公用文件就存放在
_includes
里面。这里面的公用文件,可以被_layouts
和_post
目录下面的文件嵌入。其嵌入方法,采用的是Liquid标签实现。比如:{\% include file.ext \%}
,就指在文件中嵌入公用文件_includes/file.ext
中的内容。_includes
包括的内容比如:head.html
— Code-block that defines the<head></head>
in default layout.custom-head.html
— Placeholder to allow users to add more metadata to<head />
.header.html
— Defines the site’s main header section. By default, pages with a definedtitle
attribute will have links displayed here.footer.html
— Defines the site’s footer section.google-analytics.html
— Inserts Google Analytics module (active only in production environment).disqus_comments.html
— Code to markup disqus comment box.social.html
— Renders social-media icons based on theminima:social_links
data in the config file.social-item.html
— Template to render individual list-item containing graphic link to configured social-profile.social-links/*.svg
— SVG markup components of supported social-icons.
-
_layouts
Files in the_layouts/
directory can be used as page templates.- All the repeating code on our site like the header, footer and navigation are typically in a layout.
-
assets
put your custorm css or javascript files here.- I put my custom css in
/assets/css/style.scss
.
- I put my custom css in
-
_sass
These are sass partials that can be imported into yourmain.scss
which will then be processed into a single stylesheetmain.css
that defines the styles to be used by your site.-
Jekyll provides built-in support for Sass and can work with CoffeeScript via a Ruby gem. In order to use them, you must first create a file with the proper extension name (one of
.sass
,.scss
, or.coffee
) and start the file with two lines of triple dashes, not need to write front matter, like this:--- --- // start content .my-definition font-size: 1.2em
Jekyll treats these files the same as a regular page, in that the output file will be placed in the same directory that it came from. For instance, if you have a file named
css/styles.scss
in your site’s source folder, Jekyll will process it and put it in your site’s destination folder undercss/styles.css
.
-
-
_site
这个目录,是jekyll运行之后生成的。存放着整个网站的最终静态页面。其中的内容,不用去关心。 -
Pages are the most basic building block for content.
-
The simplest way of adding a page is to add an HTML file in the root directory with a suitable filename. You can also write a page in Markdown using a
.md
extension and front matter which converts to HTML on build. For a site with a homepage, an about page, and a contact page, here’s what the root directory and associated URLs might look like:. ├── about.md # => http://example.com/about.html ├── contact.html # => http://example.com/contact.html └── index.html # => http://example.com/
-
index.html
contents in this file will show on the home page.
-
Categories or Tags
The hallmark difference between categories and tags is that categories of a post may be incorporated into the generated URLfor the post, while tags cannot be.
-
add
category
variable in the front matter of each post.category: study categories: [life, drive] tag: study tags: [life, drive]
-
creating a category page. Using the
category
frontmatter variable, we can make a categories page calledcategories.md
in the_pages
directory where you can categorize and list each post by its category like so.
Useful references:
- https://www.amitmerchant.com/how-to-categorize-your-posts-in-jekyll/
- use a
Collection
to organize categories and tags
https://jekyllrb.com/docs/collections/
Build Jekyll locally
This allows you to use plugins not supported by Github Pages.
References:
- https://scaomath.github.io/blog/custom-plugins-jekyll-github/
- https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site
Github Pages only supports certain plugins.
Two ways to build Jekyll websites:
-
Build with GitHub Pages
In one sentence: write a GitHub Actions workflow to publish your site.
GitHub Actions: https://docs.github.com/en/actions/use-cases-and-examples/building-and-testing/building-and-testing-ruby
pros: simpler to get a site set up; don’t need to manage branches;
cons: restricted whitelisted plugins and themes can be used.
GitHub now provides you with the option to use their in-house CI/CD product named GitHub Actions to build and deploy (host) your Jekyll site with complete control over the build environment and gemset.
- Advantages of using
GitHub Actions
:-
can specify any Jekyll version instead of using the classic GitHub Pages-provided version at
3.9.3
;.github/workflows/jekyll.yml
:steps: - name: Setup Ruby uses: ruby/setup-ruby@ec02537da5712d66d4d50a0f33b7eb52773b5ed1 with: ruby-version: '3.1' # Not needed with a .ruby-version file - run: bundle install # Install dependencies with Bundler - run: bundle exec rake
The
setup-ruby
action takes a Ruby version as an input and configures that version on the runner.- Alternatively, you can check a
.ruby-version
file into the root of your repository andsetup-ruby
will use the version defined in that file.
The
setup-ruby
action will automatically installbundler
for you.- The version is determined by your
gemfile.lock
file. - If no version is present in your lockfile, then the latest compatible version will be installed.
- Alternatively, you can check a
-
can use any Jekyll plugins irrespective of them being whitelisted by GitHub, including any
*.rb
files placed in the_plugins
directory of your site; -
while using a custom theme is possible without Actions, it is now possible to use themes depending on features introduced in newer versions of Jekyll.
-
- Advantages of using
-
Build locally and push the build directory contents to the
gh-pages
branch on your repository.Publishing from a branch.
pros: flexible, full control of your website contents
cons: have to mange branches; one
master
branch containing build html files and onesource
branch to manage all source files.
If we want to use a custom plugin or a newer version of Jekyll, for example, the Jekyll scholar plugin page to manage .bib
files used in this research page,
group :jekyll_plugins do
gem 'jekyll-scholar'
We need to build the _site
locally in a branch other than master
or gh-pages
, and then sync and merge ONLY the built html files to either of these two branches.
-
We need to have a
master
branch, and asource
branch (any name would dodraft
,working
, etc).master
is where GitHub pages are deployed; It only include the_site
directory.source
is where we work on writing the posts, css, js, etc.source
has the entire jekyll project.- Note: It is recommended to change your default branch to
source
. Optionally, you can make thesource
branch protected to prevent it from being accidently deleted or overriden.
-
Make changes and build locally in
source
branch. This will create_site
folder._site
folder (where the site is built into) should be in the.gitignore
. -
Navigate to
master
branch,- copy files in
_site
folder to the root folder. - create
.nojekyll
in themaster
branch..nojekyll
tells the gh-pages that there is no need to build. - Meanwhile, in the
_config.yml
of thesource
branch, under theinclude
key, we need to add- .nojekyll
.
- copy files in
Troubleshooting
Issue: Faild in Ubuntu-24.04-x64 runner when trying to deploy to GitHub Pages.
Error: The current runner (ubuntu-24.04-x64) was detected as self-hosted because the platform does not match a GitHub-hosted runner image (or that image is deprecated and no longer supported).
In such a case, you should install Ruby in the $RUNNER_TOOL_CACHE yourself, for example using https://github.com/rbenv/ruby-build
You can take inspiration from this workflow for more details: https://github.com/ruby/ruby-builder/blob/master/.github/workflows/build.yml
$ ruby-build 3.1.4 /opt/hostedtoolcache/Ruby/3.1.4/x64
Once that completes successfully, mark it as complete with:
$ touch /opt/hostedtoolcache/Ruby/3.1.4/x64.complete
It is your responsibility to ensure installing Ruby like that is not done in parallel.
Fix: Your workflow is using an older version. Need to update workflow.
I found my solutions here.
Old workflow:
uses: ruby/setup-ruby@8575951200e472d5f2d95c625da0c7bec8217c42 # v1.161.0
New workflow:
uses: ruby/setup-ruby@086ffb1a2090c870a3f881cc91ea83aa4243d408 # v1.195.0
- I compared my
.github/workflows/jekyll.yml
with this script, making sure my actions versions are consistent. - I also commented out line 40 (
# ruby-version: '3.1' # Not needed with a .ruby-version file
).
Bundler default gem URI dependency error
bundler: failed to load command: jekyll (/home/runner/work/Econ-Study/Econ-Study/vendor/bundle/ruby/2.7.0/bin/jekyll)
/opt/hostedtoolcache/Ruby/2.7.2/x64/lib/ruby/gems/2.7.0/gems/bundler-2.4.22/lib/bundler/runtime.rb:304:in `check_for_activated_spec!':
You have already activated uri 0.10.0, but your Gemfile requires uri 0.12.0. Since uri is a default gem, you can either remove your dependency on it or try updating to a newer version of bundler that supports uri as a default gem. (Gem::LoadError)
Cause: The issue lies with Rubygems being outdated. If you update RubyGems, it will fix the issue.
Fix: Add the following line to jekyll.yml
(in my case, I added to line 47 after Setup Pages). It installs the required version of the uri
gem.
- run: gem install uri
Reference:
https://travis-ci.community/t/deployments-are-failing-due-to-uri-dependency/14375/3
https://github.com/orgs/community/discussions/101754
Themes
homepage: https://mmistakes.github.io/minimal-mistakes/docs/stylesheets/
stylesheets css
: https://github.com/mmistakes/minimal-mistakes/tree/master/_sass/minimal-mistakes
How to use custom css with Jekyll minima theme
-
First need to find the right
css
file path to overrule.grep "stylesheet.*css" _site/index.html
In my case I got
<link rel="stylesheet" href="/Econ-Study/assets/css/style.css"><link type="application/atom+xml" rel="alternate" href="http://localhost:4000/Econ-Study/feed.xml" title="Personal Notes" />
Therefore, I need to make changes to
/assets/css/style.css
. -
Need to do proper style inheritance. Source the active theme using
@import "minima"
. Below this header, you can add additional CSS rules as you like.--- # Only the main Sass file needs front matter (the dashes are enough) --- @import "minima/skins/classic", "minima/initialize";
How to use js
in Jekyll
js
script allows you to define some computer-customer interactions. For instance, when a user clicks a button, it will invoke some reactions.
-
Load external
js
file in the page where you want to use the function. E.g.,<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.14.2/dist/tf.min.js"></script>
-
Load project
js
file using relative url<script src="/Econ-Study/assets/js/script.js"></script>
-
If you want the script available on every page, put the call in your
base.html
orpost.html
layout file, whichever your post template is. Every page that uses that default.html layout will then call the script. That layout file can be found at_layouts/base.html
. -
If you just want it on your current page, just call it in your
some-page.md
markdown in the same way. -
If you only want to call it when it is live and DON’T want to call it while you are developing - like, for example, a google analytics script - then wrap the call in an if statement like this:
-
Note: Use Chrome $\rightarrow$ View $\rightarrow$ Developer $\rightarrow$ Inspect Element
- use
Application
to check if the website load thejs
script at all. - use
Console
to check if there is any bug in yourjs
code. If there is bug,js
cannot run. http://127.0.0.1:4000/Econ-Study/assets/
check this url to see if you find yourjs
files here.
- use
Same problem here: can’t load js file to jekyll.
https://stackoverflow.com/questions/46263180/how-to-add-javascripts-to-jekyll
https://github.com/orgs/community/discussions/68439
How to add a script tag in Jekyll: https://stackoverflow.com/a/47109176
Example: The following codes let you click the Change text
button to change the text of the header from “Hello World” to “Have a nice day”.
<h1 id="myHeader">Hello World</h1>
<button onclick="displayResult()">Change text</button>
Hello World
Things could be improved:
-
How to add sticky sidebar TOC visiable through out the document
https://shaharkadmiel.github.io/Sticky-TOC-Sidebar/
Side bar navigation and search box: https://lzone.de/blog/How-to-use-custom-CSS-with-Jekyll-Minima-theme
-
Add social media icon
https://blog.jakelee.co.uk/adding-new-social-media-link-to-minima/ -
Equations load very slowly, maybe use
svg
(Scalable Vector Graphics) to speed up loading?Used to define vector-based graphics for the Web.
-
Sort by
update
if the object exists, otherwise sort bydate
. In other word, sort bylatest(date, update)
, whichever is the latest.Might need to use Ruby or JavaScript.
http://sfriederichs.github.io/how-to/jekyll/2016/11/08/Nothing.htmlFirst you must set the
update
field in the front-matter. If you decide not to set the field, then theupdate
date falls back to thedate
field in the front-matter.A tutorial how to sort by
update
in WordPress:https://www.namehero.com/blog/how-to-sort-posts-by-the-last-modified-date/
Add the following code to your theme’s
functions.ph
p file:function sort_by_modified( $wp_query ) { global $pagenow; if ( ‘edit.php’ == $pagenow) { $wp_query->set( ‘orderby’, ‘modified’ ); $wp_query->set( ‘order’, ‘ASC’ ); } } add_filter(‘pre_get_posts’, ‘sort_by_modified’ );
In Jekyll:
But then you have to specify the update
property for every post. reverse
makes it sorted descending, i.e., from newest to oldest.
-
Publish a series of blogs using
Bookdown
. Such as the following website:
https://josephsdavid.github.io/tstest/ -
Course website with Rmd
Github repo: https://github.com/ryantibs/timeseries-f23/tree/main
Website: https://www.stat.berkeley.edu/~ryantibs/timeseries-f23/
Setup Tutorial: https://bookdown.org/yihui/blogdown/github-pages.html