I veer away from CSS frameworks like Bootstrap because they result in sterilized designs. On a recent side project, I gave Tailwindcss a try and am now a believer. It strikes the perfect balance of design flexibility and rapid iteration.

Case in point: I rebuilt my Hugo theme, Henry, with Tailwind in three days1. I quite like how it’s turned out. Let me show you how to add it to a Hugo theme.

Approach

I like to keep things as simple as possible. So, it was important for me to use both Hugo & Tailwind as you would independently.

Two key differences in my approach:

  1. I don’t use Tailwind as a PostCSS plugin as much of the internet recommends.
  2. I keep the input css in my theme’s asset folder, but the compiled output css goes into the blog’s asset folder. This might seem like a curious choice, but it makes sense to me. People often add styling to pages in their blog folder that won’t reside in the theme. My own website doesn’t ship the index or landing page with my theme.

Installation

From your root hugo project directory:

# navigate to your theme directory
cd themes/henry

# create a package.json file (with default options)
npm init -y

# install Tailwind CSS as a dependency
npm install -D tailwindcss

# create the tailwind.config.js config file
npx tailwindcss init

Now tell Tailwind what files to watch for changes:

// tailwind.config.js
module.exports = {
    content: [

		/* relevant files from the blog */
        "../../content/**/*.{html,md}",
        "../../layouts/**/*.html",

		/* relevant files from the theme */
        "./layouts/**/*.html",
    ],
    // ... 
}

Add Tailwind to your blog.

/* blog-hugo/themes/henry/assets/css/input.css */

@import "fonts.css"; /* or other custom css you want */

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

That’s it! Fire up Tailwind and Hugo:

# start tailwind from the themes directory
npx tailwindcss \
		-i assets/css/input.css \
		-o ../../assets/css/output.css \
		--watch

# start hugo server from blog directory
hugo server

Bonus tip

Starting Tailwind and Hugo separately is a bore. Instead, I use a Procfile and foreman to launch them both with one command2.

I prefer this approach over the traditional unix jobs, bg & fg command foo because I can start everything in a single command. Additionally, I get color coded logs from each service simultaneously.

# Procfile.dev
css: npx tailwindcss -i assets/css/input.css -o ../../assets/css/output.css --watch
hugo: cd ../.. && hugo server --buildDrafts

Install foreman and run:

brew install foreman
foreman start -f themes/henry/Procfile.dev

For my own website, I have a ./bin/dev shell script 3 that checks if I have foreman and other tools installed and spins everything up in one shot.

Just use Henry

If you just want a solid Hugo theme that uses Tailwind and is easy to get up and running, just use Henry.


  1. That’s a lot of hand-wrangled css that I could port over pretty quickly. ↩︎

  2. A tip I picked up from Ruby on Rails days. ↩︎

  3. Yet another Ruby on Rails trick I picked up. ↩︎