2022-06-28 — 4 min read
Tagged: jekyll, ruby, tailwind

Creating a Static Site with Jekyll and Tailwind CSS

Your mission, should you choose to accept it, is to create a blog / static site using Jekyll, with Tailwind CSS to style it, and host it on Cloudflare Pages.

Well, I guess we won’t have to call Ethan Hunt to handle this, it should be doable by anyone, following this step-by-step tutorial.

First, we need a working ruby environment

Maybe the easiest way is to install rbenv. There are detailed instructions on the linked page for various operating systems. Then you need to install your preferred (if you don’t have one, choose the latest stable) version of ruby.

To list the latest stable versions:

rbenv install -l
2.6.10
2.7.6
3.0.4
3.1.2
jruby-9.3.4.0
mruby-3.0.0
rbx-5.0
truffleruby-22.1.0
truffleruby+graalvm-22.1.0

From this list we can see that the latest version of the official interpreter is 3.1.2 at the time of writing this post, so we can install it with

rbenv install 3.1.2

Next, we install Jekyll

The above command set up the RubyGems package manager as well, and we’ll use that to install Jekyll and bundler, the gem dependency manager. Yep, it’s managers all the way down.

gem install jekyll bundler

After this step, we have a working, although bare-bones Jekyll installation.

Creating a new site

We could use the

jekyll new my_blog

command to create a site that has a basic theme, a sample post, and other defaults included. Jekyll will create a subfolder with the site’s name (in this case my_blog) in the current directory to contain the site’s data. If you don’t plan to tinker with the setup and just want to hit the ground running, this could be your way.

Instead of this simple path, we’ll choose the slightly more involved one, and we’ll use the

jekyll new my_blog --blank

command, which copies the bare minimum to the site’s folder, letting us do the rest.

Let’s check out the contents of the folder that Jekyll created.

cd my_blog
tree --dirsfirst
.
├── assets
│   └── css
│       └── main.scss
├── _data
├── _drafts
├── _includes
├── _layouts
│   └── default.html
├── _posts
├── _sass
│   └── main.scss
├── _config.yml
└── index.md

8 directories, 5 files

There is a detailed description of each folder/file in the docs. Before starting with the configuration, we should create a git repository to track the changes to our site. We’ll add a .gitignore file with the following content to skip the files/folders we don’t want to track:

# Ignore metadata generated by Jekyll
_site/
.sass-cache/
.jekyll-cache/
.jekyll-metadata

# Ignore folders generated by Bundler
.bundle/
vendor/

# Ignore node folder
node_modules/

Then, we create the repository and check in the current state of the site.

git init
git add .
git commit -m "Initial commit."

With the --blank option Jekyll didn’t create a Gemfile, so we’ll create it ourselves. For now, we’ll add the jekyll gem to it, as well as the webrick gem, since we are using Ruby 3.0.0+.

source 'https://rubygems.org'

gem 'jekyll'
gem 'webrick'

We can check the current state of the site by running

bundle exec jekyll serve

and pointing our browser to http://127.0.0.1:4000/.

Adding Tailwind

Since we’ll use Tailwind CSS for styling, we’ll set it up now. We’ll need node and npm. Similarly to ruby above, it’s practical to use a version manager, in Node’s case, nvm. It’ll make juggling different Node versions much easier. Installation instructions are on the linked nvm page.

For Tailwind, we’ll install five npm packages:

npm install -D tailwindcss @tailwindcss/typography postcss autoprefixer cssnano

We’ll also use the jekyll-postcss gem to integrate postcss to the Jekyll workflow. Add the following line to Gemfile:

gem 'jekyll-postcss'

Then, add these lines to _config.yml:

plugins:
  - jekyll-postcss

postcss:
  cache: false

The first part adds the gem as a plugin to the Jekyll build system, the second part disables caching of the generated CSS. This part is needed because Tailwind’s just-in-time compiler will regenerate the CSS every time any of the HTML sources is modified.

Next, we’ll configure postcss, so create a file named postcss.config.js, with this content:

module.exports = {
    plugins: [
        require('tailwindcss'),
        require('autoprefixer'),
        ...(process.env.JEKYLL_ENV == 'production'
            ? [require('cssnano')({ preset: 'default' })]
            : [])
    ]
}

This will add three previously installed plugins to postcss. cssnano will only be added if we specified the production environment for Jekyll, since that’s the only case when we need to optimize the generated CSS.

We’ll also need to configure Tailwind itself, with a file named tailwind.config.js, the contents should be this:

module.exports = {
    darkMode: "class",
    content: [
        "./_drafts/**/*.{html,md}",
        "./_posts/**/*.{html,md}",
        "./_includes/**/*.{html,md}",
        "./_layouts/**/*.{html,md}",
        "./*.{html,md}",
    ],
    theme: {
        extend: {},
    },
    plugins: [
        require('@tailwindcss/typography'),
    ],
}

What you should put in content varies depending on your site structure, and where your .html and .md files will be. By default, Jekyll stores drafts in the _drafts folder and finished posts in the _posts folder, but you can devise any structure you like, and then you should simply update the lines in the content array. My site will have a dark mode toggle, so I also added a line that tells Tailwind that dark mode is toggled by a class and not set by OS preference.

Since the vast majority of our CSS will be written as Tailwind classes in the HTML files, we won’t use the Sass CSS preprocessor integrated with Jekyll. So we’ll remove the _sass folder and rename the assets/css/main.scss file to assets/css/main.css, replacing its content with this:

---
---

@tailwind base;
@tailwind components;
@tailwind utilities;

The two triple-dashed lines (front matter) need to be added so Jekyll will process the file. Then we simply add the directives for each tailwind layer.

What remains is to add a link to the generated CSS to our layout:

<link rel="stylesheet" href="{{ "/assets/css/main.css" | relative_url }}">

Whew! That’s all it took to add Tailwind to our site.

Useful Jekyll plugins

You can find tons of useful Jekyll plugins on the Awesome Jekyll Plugins list. These are the ones that I currently use:

Things you’ll also need

A favicon is, while not strictly necessary, nice to have. There are many online favicon generators, like https://favicon.io/, if you don’t have one already. They even have code snippets to include in your HTML.

In case someone tries to visit an invalid URL of the site, they’ll get an unfriendly message about the page not being available. To fix this, we’ll need a proper 404 page. Since we’ll host the site on Cloudflare, we’ll need to place a 404.html page at the root of the site, mine simply redirects to the notes archive (/notes).

We’ll wrap up the first part here. We have a functioning site, but it’s without any styling at the moment. I have a post about layouts here. We also don’t have it online yet, but we can test the functionality locally. I wrote a separate post about hosting our static site on Cloudflare Pages.

Thanks for reading! If you have any comments, additions, or corrections, feel free to reach me via e-mail.

Copyright © 2023 csm.hu
Contact