How to Make a New Jekyll Website from Scratch
In 2001, Ben and Mena Trott from San Francisco changed the world (or at least the World Wide Web) by introducing a tool called Movable Type.
The idea was to use database content to automatically generate a website. When the data changed, the website could be automatically re-generated with the new content.
This gave birth to static website generators.
Fast forward to 2008, another tool called Jekyll was created. Instead of attempting to be a full-blown Content Management System like Movable Type, it aimed to be a simple, easy-to-use, and fast static website generator. No database was needed, generation performance was lightning fast in comparison, and it was 100% open source.
The tool quickly gained popularity among developers and tech-savvy bloggers. Its simplicity and GitHub Pages integration made it perfect for personal blogs and project documentation. Writing in Markdown and using Liquid for templating appealed to those valuing both simplicity and control.
As Jekyll grew, it fostered a vibrant ecosystem of themes and plugins. The community expanded, contributing to its functionality. This growth aligned with a broader trend towards static site generators, with Jekyll often seen as a pioneer.
Why Jekyll?
Since its inception, many others have joined the party, and in 2024 we are looking at literally hundreds of SWGs. In specific areas, many beat Jekyll:
- Hugo: Much faster, able to generate websites in a fraction of the time it takes Jekyll, making it very useful for an extremely large volume of content that changes often.
- Hexo: Offers one-command deployment to various platforms like GitHub Pages, Heroku, and more, streamlining the process compared to Jekyll’s more manual deployment approach.
- Gatsby: Leverages React and GraphQL, making it ideal for developers who are familiar with these technologies. It excels at creating complex, dynamic-feeling static sites with seamless integration of the React ecosystem.
But unless one heavily relies on a particular area, selecting any mature product is likely good enough. For quite a while, Jekyll has been a complete product. With so many years under its belt, it is more mature and fleshed out than almost any other SWG on the market.
Its code on GitHub is updated almost daily. Twelve years in the making, and it is still vibrantly developed and continuously improving.
Installing Jekyll
The official Jekyll website has an excellent installation guide for multiple operating systems. Here is a link to their installation docs. Return once Ruby and Jekyll are installed.
Creating a blank Jekyll project
What the official Jekyll website doesn’t cover at the time of writing this article is how to create an empty Jekyll project.
When Jekyll generates a new website, it automatically adds a theme called Minima. This creates some unnecessary content that is good for newbies, but it forces the user to remove all that content while adding own custom content.
To create an “empty” Jekyll project, we need to add a ’–blank’ flag.
Open a terminal, navigate to the directory where you want your new Jekyll project to be stored, and write:
…where my-site-name is the name you want to give to your project.
The minimal (Minima-less) installation creates the critical directory structure, and the entire project takes less than 1KB of hard disk space.
Editing config file
Let’s start with the most important file in the whole project - _config.yml. It is always present in your main directory. Let’s open it up and edit some things.
Initially, only the first three positions listed below will be present, but we will be adding plenty more.
- url: Insert the full domain name with the extension, for example, mynewstore.com.
- baseurl: Only change this when you are not the domain owner and your website will be deeper in the directory structure. For example, if your university at https://www.university.edu hosts student websites at https://www.university.edu/~username/blog, the url setting should be https://www.university.edu and the baseurl setting should be /~username/blog.
- title: Name of your website.
- markdown: kramdown: Since Jekyll 3.0, Kramdown is the default markup language. Specifying it is not needed, but it can serve as a reference if you want to check the Markdown syntax but forgot which Markdown version is in use.
- highlighter: rouge: If you intend to have programming code examples in your articles, Jekyll has a highlighter plugin that colors your code, making it considerably easier to read.
- permalink: /:categories/:year/:month/:day/:title:output_ext: Default address structure of all articles on your website. A newly created article named ‘My new article’ written on 2024.07.02 under a ‘Travel’ category will end up with a URL address similar to: https://www.mydomain.com/travel/2024/07/02/my-new-article. You can modify placeholders to your liking or remove them entirely. Always remember to separate them with ‘/’.
- plugins: There are many Jekyll plugins. Two interesting ones are jekyll-feed and jekyll-paginate-v2. jekyll-feed automatically generates an XML file containing the entire structure of your website, making your website ready for RSS readers. jekyll-paginate organizes your articles so that they are displayed on multiple pages, for example, 10 articles per page, instead of all being displayed on one page. Installation and configuration of both are simple—just ask Chat GPT!
Creating necessary HTML files
Three types of HTML files are on almost any website out there: index, 404, and about. You need the first two; the third one you don’t, but you should still have.
By default, Jekyll only creates an index.md file in the main project folder. I recommend deleting it and creating index.html instead, along with 404.html and about.html.
Front Matter
Jekyll uses something called Front Matter, which is expected at the beginning of every HTML and Markdown file in your project.
Front Matter provides basic information about the content inside the file, so it can later be generated into a website according to the proper design layout, placed in the correct category, have the correct URL address, etc.
Front Matter must be positioned at the top of the file. Its initial and final lines only contain ’—‘, and in between are lines containing different variables and their values, one variable per line.
Below are the ten most useful Front Matter variables. Make sure to include title and layout in every Front Matter section! These are critical as every website needs a title and a layout for generating the content.
For blog posts, date, author, and at least one of the tags variables should also be present.
- title: “My First Blog Post”: Page title.
- date: 2024-07-02 14:30:00 -0200: Last piece of data is your timezone.
- categories: [web development, jekyll]: As many categories as you like. Remember to keep them inside square brackets.
- tags: [tutorial, beginner]: Same format as categories.
- layout: page/post/something else: Every markdown page is dressed in HTML according to the layout specified. More details later.
- author: Mostly used in blog posts.
- description: What is this page’s content about?
- permalink: If you specify it, the default permalink gets replaced.
- published: False: If false is specified, the document will not be part of the generated website. Useful when you need to temporarily remove the document from your website, such as an article containing statements needing updating.
- custom variables: You can create your own variables to be used in multiple ways. For example, you could specify reading_time: 5 and then in the layout file include <p>Reading time: minutes</p> to automatically insert the specified time.
Gemfile
A Gemfile is a file used by Ruby (and thus Jekyll) to manage dependencies. It lists the gems (Ruby libraries) your project needs.
When creating a Jekyll website with the ’–blank’ flag, the file is not created. Create a file named Gemfile (no extension) in your Jekyll project’s root directory and open it for editing. Add the following lines:
- source “https://rubygems.org”: This line specifies where Ruby should look for gems. RubyGems.org is the default and most common source.
- gem “jekyll”: This line tells Bundler to include the Jekyll gem in your project.
- gem “jekyll”, “~> 4.0”: An alternative version of the line above. It means: compatible with 4.0 but newer versions. This specification is called a pessimistic version constraint and serves to protect our project against compatibility issues that updating to newer versions of Jekyll might generate.
All other plugins need to be included in the file as well, one per line, using the same format, i.e., ‘gem “plugin-name”‘.
Other files in main directory
There can be multiple other types of files in the main project directory. Some examples:
- favicon-16x16.png, favicon-32x32.png: Two most basic favicon types of files, best to reside in the main directory.
- CNAME: If the website is on a custom domain, a CNAME file containing the domain address needs to be put in the main folder; otherwise, the custom domain won’t work.
- .gitignore: In case the main project folder is being put on GitHub (as opposed to just the generated final page content), the .gitignore file specifies cache and other folders that should not be pushed and synced.
- README.md: A markdown file providing information about the project, often displayed on GitHub.
- LICENSE: A file detailing the license under which the project is distributed.
- .editorconfig: Helps maintain consistent coding styles across different editors and IDEs.
- package.json: Used if the project incorporates npm packages or scripts, often for asset processing.
- .travis.yml or .github/workflows/ci.yml: Configuration files for continuous integration services like Travis CI or GitHub Actions.
Folders
One of the biggest advantages of Jekyll is its simplicity. It’s very easy to learn, as evidenced by the fact that almost everything can be contained in one mid-length article that you are reading right now.
To work efficiently in Jekyll, it’s best to learn and remember the different types of folders early. Luckily, it’s just one minute of effort.
- _posts/: Contains your blog posts.
- _pages/: Holds static pages, ie. complete html documents that don’t need to be generated each time. Some projects use a dedicated _pages folder, while others place pages directly in the root. In general, if there are only few HTML documents (like earlier mentioned: index.html, about.html, 404.html) and main project folder is not crowded, there’s no need to create an extra folder.
- _layouts/: Contains templates that wrap around your content. These define the overall structure of different types of pages.
- _includes/: Stores reusable content snippets that can be included in layouts, pages, or posts.
- _data/: YAML, JSON, or CSV files containing data that can be accessed via the site.data variable in templates.
- _sass/: Contains partial Sass files that can be imported into your main CSS file.
- assets/ or _assets/: Stores static files like images, CSS files, and JavaScript files.
- _site/: The generated site directory (usually ignored in version control). This is where Jekyll outputs the final, static website. It is also where you want to initiate a git repository if you are using Github Pages to host your website.
- _drafts/: A place for unpublished posts. These won’t appear on the live site unless Jekyll is run with the ’–drafts’ switch.
- _plugins/ or _extensions/: Contains custom Ruby plugins to extend Jekyll’s functionality.
- collections/ or custom collection folders: Holds files for custom collections, which are similar to posts but can be organized differently.
Following are extended descriptions of some of the folders above, describing what kind of work has to be done in which folders in the process of creating, maintaining, and updating a Jekyll website.
_posts
The _posts folder is a cornerstone of Jekyll’s blogging functionality. It serves as the primary location for storing blog post content in a Jekyll site. This folder is created by default when you initialize a new Jekyll project.
Within the _posts folder, individual blog posts are stored as separate files. These files follow a specific naming convention: YYYY-MM-DD-title.md (or .markdown). For example, ‘2023-07-02-welcome-to-jekyll.md’. This naming structure is crucial as Jekyll uses it to extract the publication date and create the post’s URL.
Each post file in the _posts folder typically begins with YAML front matter, enclosed between triple-dashed lines. This front matter contains metadata about the post, such as the title, date, categories, tags, and any custom variables you define. The content following the front matter is the main body of your blog post, usually written in Markdown.
Jekyll processes these files, converting the Markdown to HTML and applying the appropriate layout as specified in the front matter or your configuration. The resulting HTML files are then placed in the appropriate location within your generated site, typically under a /blog/ or /posts/ directory, depending on your permalink settings.
The _posts folder is dynamic, meaning you can continually add new post files, and Jekyll will automatically include them in your site when you build it using jekyll build or jekyll serve commands. This makes it easy to maintain and grow your blog over time, simply by adding new files to this folder.
_layouts
The _layouts folder is a crucial component of Jekyll’s theming system. It contains template files that define the structure and appearance of different types of pages on your site. These templates act as the skeleton for your content, providing consistent styling and structure across your site.
Layout files are typically HTML documents with Liquid tags and variables. They include placeholders for content, which Jekyll fills in when generating your site. The most common layout is default.html, which often serves as the base template for other layouts.
Other common layouts might include post.html for blog posts, page.html for static pages, and home.html for the homepage. You can create as many custom layouts as you need for different types of content or sections of your site.
In your content files (posts, pages, etc.), you specify which layout to use in the front matter. For example, ‘layout: post’ tells Jekyll to wrap that content in the post.html layout. If no layout is specified, Jekyll defaults to default.html.
Layouts can be nested. For instance, a post.html layout might include the content within a default.html layout, adding post-specific elements like author information or publication date. This nesting allows for modularity and reuse of common elements across different page types.
The _layouts folder gives you fine-grained control over your site’s structure and appearance. By editing these files, you can make site-wide changes efficiently, ensure consistency across pages, and create a unique look for your Jekyll site without repeating HTML structure in every content file.
_includes
The _includes folder in Jekyll is designed to store reusable content snippets. These snippets can be HTML, Markdown, or Liquid code that you want to use across multiple pages or layouts in your site. This folder helps in keeping your code DRY (Don’t Repeat Yourself) and makes maintenance easier.
Common uses for includes are elements like headers, footers, navigation menus, sidebar content, or any other repetitive parts of your site. By storing these elements in separate files within the _includes folder, you can easily update them in one place and have the changes reflect across your entire site.
To use an include in your layouts, pages, or posts, you simply use the Liquid tag ’{% include file.html %}’. Jekyll will then insert the contents of the specified file from the _includes folder at that point in your document. You can also pass parameters to includes, allowing for more dynamic and flexible use of these snippets.
The _includes folder is particularly useful for creating modular designs. It allows you to break down your site into smaller, manageable pieces, making it easier to update and maintain. This modularity also facilitates collaboration on larger projects, as different team members can work on different components without conflicting with each other’s work.
_assets
The _assets folder (or sometimes simply assets) is a common directory in Jekyll projects used to store static files that are part of your website. While not a default Jekyll folder, it’s widely adopted by developers as a best practice for organizing non-content files.
This folder typically contains subdirectories for different types of assets. Common subdirectories include images for storing graphics and photos, css for stylesheets, js for JavaScript files, and fonts for custom web fonts. This organization helps keep your project structure clean and logical.
Unlike content in folders like _posts or _pages, files in the _assets folder are not processed by Jekyll’s templating system. They are typically copied as-is to the _site folder when your site is built. However, many Jekyll setups use additional plugins or build processes to optimize these assets, such as minifying CSS and JavaScript or compressing images.
To reference files from the _assets folder in your layouts, includes, or content, you’ll typically use Jekyll’s ‘site.baseurl’ variable combined with the file path. This ensures that your assets are correctly linked regardless of where your site is deployed.
It’s worth noting that while _assets (with an underscore) is commonly used, some developers prefer assets without the underscore. The underscore version isn’t processed by Jekyll, which can be useful for certain setups, while the non-underscore version allows for easier direct linking in some deployment scenarios. The choice often depends on your specific needs and workflow.
Blog update routine
Working with Jekyll daily typically involves writing new articles and updating the website with those articles. Assuming _config.yml, Gemfile, and other necessary files are already created and configured, the update cycle generally follows these steps:
- Create a new post:
- Navigate to your project’s _posts folder.
- Create a new file using the format YYYY-MM-DD-article-title.md. For example, 2024-07-02-My-First-Article.md.
- Write the article:
- Start the file with Front Matter. Begin and end the Front Matter with three dashes (’—‘), and specify metadata like title, date, categories, and tags.
- Write the main content of your article in Markdown.
- Preview locally:
- Open a terminal, navigate to your Jekyll project directory, and run ‘jekyll serve’.
- Jekyll will build your site and serve it locally at ‘http://127.0.0.1:4000’.
- Open this address in your web browser to preview your changes in real-time as you write.
- Finalize the Article:
- Insert images, format text (using bold, italic, etc.), and structure your paragraphs.
- Once satisfied, stop the local server by pressing ‘Ctrl+C’ twice in the terminal.
Congratulations, your website is ready for upload!
Uploading to Github
Github is very generous to static website owners, allowing them to upload websites for free with no catch to its Github Pages, so long as each website does not exceed 1GB in total size and there are no files larger than 100MB.
It is generally recommended to sign up to Github Pages instead of uploading a static website to a custom ftp server. Such server will be paid, almost guaranteed to perform worse than Github Pages and will have worse uptime.
Here is how to do this:
-
Download Git for Windows from official website
-
Open a new terminal window and input these commands:
-
Navigate in terminal to your Jekyll project.
-
Initialize git repository with git init. Initializing is creating a git repository, you only have to do it once.
-
Write these commands. In second command, replace content in quotes with easy to understand and short description of what this particular update brings to your website.
- Set up SSH for passwordless authentication:
- Generate an SSH key: ssh-keygen -t rsa -b 4096 -C “your.email@example.com”
- Start the ssh-agent: eval $(ssh-agent -s)
- Add your SSH key to the agent: ssh-add ~/.ssh/id_rsa
- Add your SSH key to GitHub:
- Copy your public key to clipboard: clip < ~/.ssh/id_rsa.pub
- Go to GitHub.com and log in
- Click your profile photo > Settings > SSH and GPG keys
- Click “New SSH key”
- Give it a title and paste your key into the “Key” field
- Click “Add SSH key”
- Connect your local repository to GitHub:
- Create a new repository on GitHub (without initializing with README)
- In Git Bash, add the remote repository: git remote add origin git@github.com:username/repository.git
- Push your code to GitHub: git push -u origin master
Now you should be able to push and pull from your GitHub repository without entering a password each time.
Steps 6-8 are needed to perform just once. From now on, after you finish writing an article and quit Jekyll, routing uploading to Github Pages requires only 3 commands:
Useful Kramdown notation
Kramdown, a Markdown parser used in Jekyll, provides a simple way to format your articles. Here are some commonly used Kramdown notations:
- #, ##, ###: Create headers of decreasing size. More # symbols mean smaller headers (# is H1, ## is H2 etc.)
- * , _ , **: Create emphasis. Single * or _ for italics, double ** or __ for bold.
- - , + , *: Start unordered list items. Numbers followed by periods (1., 2., etc.) start ordered lists.
- []: Enclose link text. () immediately after contains the URL.
- {:target=”_blank”} at the end of a link opens it in new tab
- !: Placed before [] to indicate an image. [] contains alt text, () contains image URL.
- —, ***, ___: Any of these on a line by themselves creates a horizontal rule. Exceptions are Front Matter borders whichh will not produce html objects.
- : : Separates a term from its definition in definition lists.
Final word
Jekyll is a powerful yet straightforward tool that allows developers to create static websites with ease. Its structured folder system, which includes _posts, _layouts, _includes, and _assets, facilitates organized content management and site customization. By leveraging Markdown for content creation, Jekyll simplifies the writing process, enabling users to focus on their message rather than the intricacies of HTML.
The ability to seamlessly update and preview changes locally, combined with the straightforward process of deploying updates to GitHub Pages, ensures that maintaining and growing your website is a smooth and efficient experience. By adhering to best practices and utilizing tools like Git and Kramdown, developers can ensure their sites are not only visually appealing but also robust and maintainable.
Whether you are a seasoned developer or a newcomer to web development, Jekyll offers a streamlined path to building and managing a successful static website. Its user-friendly approach and powerful features make it an excellent choice for anyone looking to create a well-organized, professional web presence.