Last updated: August 21, 2025

Jekyll

What is Jekyll

Jekyll is a static site generator. This means that if run the command jekyll build, within a folder in which there is a Gemfile (jekyll is written in Ruby) and a bunch of folders and files appropriately organized, the command will produce a website ready to be host on web server.

Installation

Jekyll is written in Ruby, an interpreted language. Thus, you need an interpreter to use Jekyll. Most Linux distro have an officially supported interpreter that you can install using the packet manager. For example in Linux Mint I use:

sudo apt install ruby-full

This command actually installs automatically a whole bunch of packages, in addition to ruby. I am not sure whether they are all needed in order to properly run Jekyll, but for sure ruby-rubygems is needed.

Addionally, you need to have GCC and Make. GCC (the GNU Compiler Collection) is a bundle of compilers and libraries for C, C++, and many other languages. Make is a tool for automation widely used in multiple context. If you have a Linux distro, you probably already have both of them.

To install Jekyll you use the command gem provided by the tool RubyGems. RubyGems is a package manager for Ruby. A package distrubuted through RubyGems is called a gem. We will install two gems: jekyll and bundler. I am not sure why we need bundler. It seems to provide a “wrapping environment” in which to execute other gems. For example instead of executing directing the command jekyll serve, we will do bundle exec jekyll serve. But the result is the same, so not sure.

Install using gem:

gem install --user-install jekyll bundler

It is important to use the –user-install flag, otherwise gem will probably try to install the gems in a sudo-protected folder (where ruby was probably installed). The user-installed gems are (at least in my case) in ~/.local/share/gem/ruby/3.2.0/bin. We need to add it to the PATH variable in order to be able to execute our gems. So we add this line to out .bashrc file:

export PATH="~/.local/share/gem/ruby/3.2.0/bin:$PATH"

Troubleshooting

If you get a permission error when you try to install a gem, it is probably because it is trying to install it in a folder with sudo privileges. Just use the --user-install flag to solve the problem.

Usage

jekyll new /PATH/TO/FOLDER

Use this command to build the website and host it at localhost:4000. Every time you change a file the website will be rebuilt.

jekyll serve

Use this command if you have gemfile:

bundle exec jekyll serve

Minimal Website Structure

To understand Jekyll, I hoped that reading the documentation on the website would have been enough. Unfortunately, it seems limited to the bare minimum. Thus, I try to build a website from scratch.

First I create a directory for my website:

mkdir TestWebsite

Then I use the command:

jekyll new TestWebsite/ --blank

which creates new jekyll site with the basic structure and nothing else. I run jekyll serve or jekyll build to see how it looks: it is just a blank page with written “you are ready to go”.

The basic structure includes:

  • empty folders (_data, _drafts, _includes, _posts)
  • a folder _layouts containing a single layout called default.html
  • a folder _sass containing a single file base.scss
  • a folder assets/css containing a single file main.scss
  • a file _config.yml and a file index.md

After I run the command jekyll build the following folders are created:

  • .jekyll-cache, which probably contains just some info used to speedup subsequent builds on the website
  • a folder _site containing a file index.html and a folder assets/css Importantly, this last folder is the website: just a collection of .html files, telling the browser what to draw, and .css files, telling the browser how to draw.

Sass - how to handle style

Sass stands for Syntactically Awesome Style Sheets. It is a ‘preprocessor’ or an ‘extension language’ for CSS. The idea is that instead of writing your stylesheets directly in CSS (.css files), you write them in SCSS (.scss or .sass files), which are then automatically converted into .css files. The SCSS language adds features, like variables, to make the stylesheets more mantainable and powerful.

The basic workflow when working with SCSS, is to make a set of .scss files containing styling options might be used on multiple pages. These files are called partials. Then, for each page that you need to style, you make .scss file in which you import all the partials needed. A file where partials are imported to is called a manifest file. Depending on the way you want to structure your Sass project, a partial can contain all variables used in your project, functions or mixins or it might be for specific pages or components of your pages.

Now, Jekyll uses Sass by default, as one can see by creating a blank website and looking at folders:

  • a folder _sass (partials folder) containing a single file base.scss
  • a folder assets/css containing a single file main.scss

When you execute jekyll build, these files are use to build the files in _site/assets/css. This functionality is bundled with Jekyll through the jekyll-sass-converter plugin, which is enabled by default. Notice that the file assets/css/main.scss starts with the two lines (front matter):

---
---

which tell Jekyll that this file needs to be processed, and not simply copied.

The location of all the SCSS partials has to be specified in the _config.ylm file, by setting the value of sass_dir. By default, the value is _sass, and that is why the folder _sass was automatically created, with the partial base.scss. Files within this directory should not contain front matter, as they are intended for imports only.

To be honest, the organization is Sass partials is a bit too much for a personal website, like mine. At least, it feels so at the moment. I am not sure whether I want to keep it.

Exploration

The file _config.yml looks very important in the Academics template. Oh well, to organize my notes page, it seems like I have to read of Jekyll works for real. I realized I am “killing” jekyll phylosophy. It is like I am using a hammer to hit my target with the wooden handle. This is because every time a make some new content (write a new note), I have also to go the notes page and udpdate the table in order to add the note. In Jekyll, this process should be all automated, so that you just focus on writing content, and the mental bargain of updating your website is way lower.

Now the first thing I want to do is to add some text, describing myself, in the index.md page, and also a picture. To do that, I try to follow the organization from academicpages and/or al-folio (from now on called “the guys”).

They both moved the index.md basic page into the folder _pages. Now big question: if I do it, will the website still build correctly? Only a way to find out. Nope! I mean the build went fine, but the generated site is different: the is no index.html file anymore. The _pages folder was completely ignored. So let us see where the guys cites this folder. Ah-ah, they added this line in their _config.yml file:

include: ["_pages"]

If I do it as well, the site has now another folder _pages containing the index.html file. However, this is not displayed as the first page when I open the website with jekyll serve running. How to tell Jekyll that that is my main page? Well the main page of the guys I think is called about.md, let us see were they mention it. Mmh, nowhere interesting. But it might be referred somewhere so that it is set as the main page. One explanation could be that all the pages in the _pages folder are included with a single statement, or maybe they loop over them, so the name is never actually referred. So let us look again for _pages. Nope, nothing useful. Maybe where the page about.md goes is specified within the content of the file itself, i.e. in its header (which I think Jekyll calls “front matter”). There are many things there, that the basic file index.html does not have. The most interesting seems permalink. Ye babe! I added to the front matter of:

permalink: /

and now index.html is the root of my website. The site built looks now exacly like in the beginning, before creating the _pages folder.

I added some text in the index.html, point at other webpages (emtpy for now) that I created in the _pages folder. To point at other webpages I simply add to use the link syntax of markdown, where the link to ther local page is obtained with a Liquid command, like this:

[CV](/cv)

Nice, time to add an image of myself! Here the guys do not agree: academicpages has a folder /images, while al-folio has a folder /assets/img/. I guess this is an arbitrary choice. To avoid making the root too crowded, I go for a folder /assets/images/, and put my pic inside. The guys have a picture called profile_pic.jpg or similar, let us follow that. I know they like cut the image in circular shape, so there must be some script it is connected to. A lot to learn, ye. So, al-folio refers it only in the front matter of about.md, under the profile:image keyword. While academicpages refers it in the _config.yml under the keyword avatar. I guess we need to follow this keywords now. I choose to follow al-folio because it should be simpler (according to how its website looks).

The important file seems to be about.liquid, which is a layout (since it is in the _layouts folder). It does not sound right to have a layout just for a specific page. Indeed, academicpages does not have it, and the layout of its about.md is default.html (I guess, since it is not specified). Moreover, the some code is repeated identical in the layout profiles.liquid. Let us see what this code does. First I notice that the main structure is actually html, thus I like more the extension .html, like academicpages thus (and also like the priginal jekyll blank website).

The main html element of interest seems a div. But is the variable site.max_width automatically defined? Let us try to use this snippet in my index.md. Ok, of course we miss the file figure.liquid. This is in the _includes folder, and it provides a single html figure element. To do that though, it uses a lot of Liquid commands, and invokes also imagemagick. Instead, academicpages does not use any tool apparently, it looks more elegant but more difficult to understand. It seems to be overcomplicated for what I want to do. I will just use basic html elements and css for floating behavior I guess. So I just added this (thanks ChatGPT):

<img src="/assets/images/profile.jpg" alt="Profile picture" 
     style="float: right; margin-left: 10px; margin-right: 50px; width: 200px;">

Not rounded, but not bad! Actually to round it I just had to add a stylying option.

The next thing we want to do is add a navigation bar at the top. We need to follow closely the guys because I want my website to be mobile friendly as theirs.

Ok I got fed up of following the guys, because everything is so convoluted and complicated, and I want something simple. On the other hand, I still miss a whole understanding of Jekyll workflow. You know who has it instead? ChatGPT. I asked it this:

I would like to add a page titled 'Personal Notes'. This page should present links to all the markdown files in the folder _data/notes/ in which some notes are written. For example the path to a note will be _data/notes/field/subfield/topic.md. The page should divide the notes in the different fields and subfields, and every time I add a new folder or a new file in the _data/notes/ it should update correctly. How to do it?

And it immediately warned me that Jekyll expects only structured data in the folder _data, not markdowns. Good ChatGPT. So here’s what we have to do:

  1. Create a _notes/ folder with the structure field/subfield/topic.md.
  2. Create a collection in _config.yml (the concept of collection is important in Jekyll).
  3. Make the page _pages/notes.md with the appropriate Liquid code to fetch the fields, subfields, topics.

To understand the idea of how Liquid code works, consider that this code:

Will write all the paths of the notes that you stored in the folder _notes. Powerful!

Support for Latex: Mathjax

Quite suprisingly to me, there is no official documentation on how to implement mathjax support. Since I am surprised, I am probably missing something. First, what is MathJax? It is a program written in JavaScript that takes latex code and renders it nicely. It is developed by the homonymous non-profit organization MathJax. The fact that is in JavaScript tells us that will work in all browsers. Thus, tecnically, Jekyll already supports MathJax, since of course it supports JavaScripts. We just have to tell Jekyll were to look for the scripts, and on the MathJax webpage they tell you exactly how to do it:

So let us try to add the script in our note layout, and see what happens.