Set up Hugo with Tailwind CSS in 2023
With the release of v0.112.0 , Hugo added the native support for TailwindCSS v3.x . The author of Hugo provided an example repository setting up TailwindCSS v3: bep/hugo-starter-tailwind-basic .
Note that it uses PostCSS so make sure to use Hugo extended version greater than v0.112.0.
How does it work?
According to the release note:
The basic concept is to add
hugo_stats.json
to the server watcher list in Hugo and trigger a new TailwindCSS build only whenever either this file or the main CSS file changes.
Add the following sections to the config.toml
or hugo.toml
configuration file:
[module]
[[module.mounts]]
source = "assets"
target = "assets"
[[module.mounts]]
source = "hugo_stats.json"
target = "assets/watching/hugo_stats.json"
[build]
writeStats = true
[[build.cachebusters]]
source = "assets/watching/hugo_stats\\.json"
target = "styles\\.css"
[[build.cachebusters]]
source = "(postcss|tailwind)\\.config\\.js"
target = "css"
[[build.cachebusters]]
source = "assets/.*\\.(js|ts|jsx|tsx)"
target = "js"
[[build.cachebusters]]
source = "assets/.*\\.(.*)$"
target = "$1"
Also update the tailwind.config.js
file to
module.exports = {
content: [
"./hugo_stats.json"
],
}
Migration
Previously, my package.json
file looks like this:
{
"scripts": {
"dev": "NODE_ENV=development ./node_modules/tailwindcss/lib/cli.js -i ./static/tailwind.css -o ./static/main.css -w",
"build": "NODE_ENV=production ./node_modules/tailwindcss/lib/cli.js -i ./static/tailwind.css -o ./static/main.css --minify"
},
"dependencies": {
"tailwindcss": "^3.2.7",
"@tailwindcss/typography": "^0.5.9"
}
}
It includes separate steps:
- Compile Tailwind CSS file to
static/main.css
- Build Hugo site
Sometimes, when making changes to styles, I had to manually restart the Hugo dev server to make it take effect.
After:
{
"devDependencies": {
"@tailwindcss/typography": "^0.5.9",
"autoprefixer": "^10.4.14",
"postcss": "^8.4.23",
"postcss-cli": "^10.1.0",
"prettier": "^2.8.8",
"prettier-plugin-go-template": "^0.0.13",
"tailwindcss": "^3.3.2"
}
}
We don’t need the above dev
and build
command since all can be done via hugo
. Win!
Create postcss.config.js
:
const tailwindConfig = process.env.HUGO_FILE_TAILWIND_CONFIG_JS || "./tailwind.config.js";
const tailwind = require("tailwindcss")(tailwindConfig);
const autoprefixer = require("autoprefixer");
module.exports = {
// eslint-disable-next-line no-process-env
plugins: [tailwind, ...(process.env.HUGO_ENVIRONMENT === "production" ? [autoprefixer] : [])],
};
I put styles.css
file under ./assets/styles
.
Then include it properly inside the Hugo html template file.
<!-- Styles -->
{{ $options := dict "inlineImports" true }}
{{ $styles := resources.Get "styles.css" }}
{{ $styles = $styles | resources.PostCSS }}
{{ if hugo.IsProduction }}
{{ $styles = $styles | minify | fingerprint | resources.PostProcess }}
{{ end }}
<link href="{{ $styles.RelPermalink }}" rel="stylesheet" />
After all these steps, the dev and build command will simply:
# dev
hugo server
# build
hugo --gc --minify
Enjoy!