Tailwind in Your Buns
My background is mostly in backend development; frontend is not my forte, but when I tried TailwindCSS in one of my previous projects, I really liked it. I decided to use it in my blog as well.
Like before, I will start by going through the official guide.
Installing TailwindCSS
The guide says to install TailwindCSS via npm but I am going to use Bun instead.
$ bun install --dev tailwindcss @tailwindcss/cli
Update site’s .gitignore
Because the site folder will also contain files for Bun, I need to ensure that .gitignore includes configuration for it as well. If you are creating a new project via bun init, you get gitignore added as your .gitignore. But in our case, because we are using bun install it won’t be added. So I will be adding it manually.
diff --git a/site/.gitignore b/site/.gitignore
index a6e26ad..517d145 100644
--- a/site/.gitignore
+++ b/site/.gitignore
@@ -1,3 +1,4 @@
+# Hugo
# Copied from: https://github.com/github/gitignore/blob/main/community/Golang/Hugo.gitignore
# License: CC0 1.0 Universal
@@ -14,3 +15,42 @@ hugo.linux
# Temporary lock file while building
/.hugo_build.lock
+
+# Bun
+# Copied from: https://github.com/oven-sh/bun/blob/main/src/cli/init/gitignore.default
+# License: MIT
+
+# dependencies (bun install)
+node_modules
+
+# output
+out
+dist
+*.tgz
+
+# code coverage
+coverage
+*.lcov
+
+# logs
+logs
+_.log
+report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
+
+# dotenv environment variable files
+.env
+.env.development.local
+.env.test.local
+.env.production.local
+.env.local
+
+# caches
+.eslintcache
+.cache
+*.tsbuildinfo
+
+# IntelliJ based IDEs
+.idea
+
+# Finder (MacOS) folder config
+.DS_Store
Update site’s configuration
Paste the code provided in Step 2.
diff --git a/site/hugo.toml b/site/hugo.toml
index 1087dd9..8e24de2 100644
--- a/site/hugo.toml
+++ b/site/hugo.toml
@@ -7,6 +7,23 @@ title = 'Blog'
[[module.imports]]
path = 'github.com/imomaliev/blog/theme'
+ [[module.mounts]]
+ source = 'assets'
+ target = 'assets'
+ [[module.mounts]]
+ disableWatch = true
+ source = 'hugo_stats.json'
+ target = 'assets/notwatching/hugo_stats.json'
+
+[build]
+ [build.buildStats]
+ enable = true
+ [[build.cachebusters]]
+ source = 'assets/notwatching/hugo_stats\.json'
+ target = 'css'
+ [[build.cachebusters]]
+ source = '(postcss|tailwind)\.config\.js'
+ target = 'css'
[caches]
[caches.images]
Update CSS entry file
Step 3 asks to create a new CSS file, but my theme already has main.css. So I will be updating it instead.
diff --git a/theme/assets/css/main.css b/theme/assets/css/main.css
index 166ade9..cae7ba4 100644
--- a/theme/assets/css/main.css
+++ b/theme/assets/css/main.css
@@ -1,3 +1,6 @@
+@import "tailwindcss";
+@source "hugo_stats.json";
+
body {
color: #222;
font-family: sans-serif;
Process CSS with TailwindCSS CLI
Update theme/layouts/_partials/head/css.html with code from Step 4.
diff --git a/theme/layouts/_partials/head/css.html b/theme/layouts/_partials/head/css.html
index d76d23a..075e64e 100644
--- a/theme/layouts/_partials/head/css.html
+++ b/theme/layouts/_partials/head/css.html
@@ -1,9 +1,12 @@
{{- with resources.Get "css/main.css" }}
- {{- if hugo.IsDevelopment }}
- <link rel="stylesheet" href="{{ .RelPermalink }}">
- {{- else }}
- {{- with . | minify | fingerprint }}
- <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
+ {{- $opts := dict "minify" (not hugo.IsDevelopment) }}
+ {{- with . | css.TailwindCSS $opts }}
+ {{- if hugo.IsDevelopment }}
+ <link rel="stylesheet" href="{{ .RelPermalink }}">
+ {{- else }}
+ {{- with . | fingerprint }}
+ <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
+ {{- end }}
{{- end }}
{{- end }}
{{- end }}
Update theme/layouts/_partials/head.html with code from Step 5.
diff --git a/theme/layouts/_partials/head.html b/theme/layouts/_partials/head.html
index 02c2240..13f1cd6 100644
--- a/theme/layouts/_partials/head.html
+++ b/theme/layouts/_partials/head.html
@@ -1,5 +1,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>{{ if .IsHome }}{{ site.Title }}{{ else }}{{ printf "%s | %s" .Title site.Title }}{{ end }}</title>
-{{ partialCached "head/css.html" . }}
+{{ with (templates.Defer (dict "key" "global")) }}
+ {{ partial "head/css.html" . }}
+{{ end }}
{{ partialCached "head/js.html" . }}
TailwindCSS is installed and configured.
Install Typography plugin
One of the reasons I prefer using TailwindCSS is its typography plugin.
$ bun install --dev @tailwindcss/typography
And add plugin to theme/assets/css/main.css
diff --git a/theme/assets/css/main.css b/theme/assets/css/main.css
index cae7ba4..66b0f49 100644
--- a/theme/assets/css/main.css
+++ b/theme/assets/css/main.css
@@ -1,5 +1,6 @@
@import "tailwindcss";
@source "hugo_stats.json";
+@plugin "@tailwindcss/typography";
body {
color: #222;
Update workflow to use Bun instead of Node
Bun provides an official GitHub Action and the guide how to use it. I’ve gone through .github/workflows/hugo.yaml and updated it to use Bun instead of Node.js
diff --git a/.github/workflows/hugo.yaml b/.github/workflows/hugo.yaml
index d8cc26d..a240bb0 100644
--- a/.github/workflows/hugo.yaml
+++ b/.github/workflows/hugo.yaml
@@ -23,7 +23,7 @@ jobs:
env:
GO_VERSION: 1.25.5
HUGO_VERSION: 0.154.4
- NODE_VERSION: 24.12.0
+ BUN_VERSION: 1.3.7
TZ: Europe/Oslo
steps:
- name: Checkout
@@ -36,10 +36,10 @@ jobs:
with:
go-version: ${{ env.GO_VERSION }}
cache: false
- - name: Setup Node.js
- uses: actions/setup-node@v6
+ - name: Setup Bun
+ uses: oven-sh/setup-bun@v2
with:
- node-version: ${{ env.NODE_VERSION }}
+ bun-version: ${{ env.BUN_VERSION }}
- name: Setup Pages
id: pages
uses: actions/configure-pages@v5
@@ -57,10 +57,11 @@ jobs:
run: |
echo "Go: $(go version)"
echo "Hugo: $(hugo version)"
- echo "Node.js: $(node --version)"
- - name: Install Node.js dependencies
+ echo "Bun: $(bun --version)"
+ - name: Install Bun dependencies
run: |
- [[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true
+ cd site/
+ [[ -f bun.lock ]] && bun install --frozen-lockfile || true
- name: Configure Git
run: |
git config core.quotepath false
The setup is complete; we are ready to style our site.