DEV Community

Sardorbek Imomaliev
Sardorbek Imomaliev

Posted on • Originally published at imomaliev.com

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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]
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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 }}
Enter fullscreen mode Exit fullscreen mode

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" . }}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

The setup is complete; we are ready to style our site.

Top comments (0)