Jekyll is a great tool for generating static blog sites for lots of reasons such as inbuild support of markdown pages, sass, and the ability to categorize your content in a beautiful hierarchy is just amazing.
Today, I’m going to show you how I created my blog theme from scratch so that you can do it too without any complexity.
Let’s start by Modelling your directory as follows.
Shortly after giving the command jekyll new-theme $theme-name for creating a Jekyll boilerplate, you’ll come across a list of Jekyll packages, some predefined HTML CSS files to get started, along with a couple of directories and files.
The obtained folder structure is something like this.

Understanding Jekyll's Folder Structure -
The boilerplate of the default generated Jekyll theme ships with mostly some empty directories, a gemfile, and a couple of ‘not so important files to define our theme, these come with no general use case.
The default directories are listed as follows -
_data
For the storage of some local data to be used.
_includes
For defining dom components without hindering the hierarchical pattern in the _layouts dir.
_layouts
The HTML pages which form the skeleton for our site are supposed to exist in this directory.
A default.html is created to put up the elements that are common to all pages e.g. Navbar, footer, etc. All other layouts are integrated inside this file.
_sass
Jekyll supports sass by default, a good practice while working with sass in Jekyll is to separate all the sass files into this folder and later include it in the only main.sass file, which is present in the Assets folder.
_Assets
The following folder is pretty self-definitive. The static assets, scripts, and main.sass are defined here.
gemfile
As the name, this file contains a list of the additional gems/plugins that you’ll use in your theme additionally. To install any third-party plugin just add the name of the plugin in quotations with gem before the name of this file and run bundle install. This installs the plugin to your theme’s configuration.
$themename
The file contains information that is required when publishing the theme.
Config.yml
This file is not present by default, Jekyll serves you with some default configuration but at some point in time, there happens to be a need to include extra configurations like 3rd party plugin, global variables, variable routing, etc.
The file assists with the logical mapping of nearly every file that exists within the theme source code.
Writing into config.yml
Create a config.yml in your root directory to start defining the configuration for the theme.
Start with defining some metadata, followed by socials, and 3rd party plugins.
Below is an example of a simple config file -
lang: en
title: "Site title" #meta
description: "Add a description" #meta
baseurl: ""
url: "" #configure after the build
# socials
twitter_username: hatchedland
github_username: hatchedland
linkedin_username: rajanydv
instagram_username: rajanydv_
sass:
sass_dir: _sass #defined the path for all the sass files present.
style: compressed
#defining dynamic routes for the blog/tag files
collections:
blog:
output: true
tags:
output: true
permalink: /blog/tags/:path/
defaults:
- scope:
path: ''
type: blog
values:
layout: post
comments: true
toc: true
permalink: /post/:title/
# Build settings
theme: nuboard-theme
#3rd party Pluggins
plugins:
- jekyll-feed
- jekyll-archives
- jekyll-seo-tag
# Comments
disqus-username: disqus_TNJRzbsQPX
Creating layouts for the pages.
Creating layouts is somewhat similar to creating dom components.
Understand this as writing different HTML for every page separately.
To get started create a default layout page, which links the head, navbar, and footer before and after the main HTML element.
For every other layout, now they all will be linked within that main component, based on the page routing.
%% Creating home page %%
Create another layout home.html, import the layout of the default template, and write some HTML for the home page.
_layouts/homelayout: "default"
After that create a markdown file in the root directory as index.html and link the home layout to it.
/home.mdlayout: "home"
Similarly, create layouts for other pages in your website, and in the root dir, create files with .md extension for accessing those layouts for their pages.
Configuring Tags
This is the part I struggled with the most when I created my Jekyll theme. What I didn’t know at that time was that Jekyll has inbuilt support for tags.. but.. but you’ll need to manually create them in those instances when your posts introduce a new tag.
To tackle these issues, create a script that will create dedicated tag files in _tags/tag-file.md.
The following code does this job elegantly.
Jekyll::Hooks.register :blog, :post_write do |post|
all_existing_tags = Dir.entries("_tags")
.map { |t| t.match(/(.*).md/) }
.compact.map { |m| m[1] }
tags = postt['tags'].reject { |t| t.empty? }
tags.each do |tag|
generate_tag_file(tag) if !all_existing_tags.include?(tag)
end
end
def generate_tag_file(tag)
File.open("_tags/#{tag}.md", "wb") do |file|
file << "---\nlayout: tags\ntag-name: #{tag}\n---\n"
end
end
Publishing the theme
After pushing the final code on GitHub, package your theme using the following command.
gem build theme-name.gemspec
Finally, push your packaged theme up to the RubyGems service, by running the following command, again replacing theme-name jekyll-theme-awesome with the name of your theme
gem push theme-name-*.gem
On every new release, append the version name on every push you make to the gem.