點燈坊

失くすものさえない今が強くなるチャンスよ

Integrating HATstack with Hugo

Sam Xiao's Avatar 2022-03-02

Hugo is great for JAMstack, but we have to use vanilla JavaScript and CSS to create templates. With Alpine and TailwindCSS, we can create layouts by declarative style directly in HTML.

Version

Hugo 0.92
Alpine 3.8
TailwindCSS 3.0

Create New Site

$ hugo new site hugo-hat --format json
  • hugo new site : create a new site with default skeloton
  • --format json : use JSON as Hugo config format

hat000

Add Packages

$ npm install -D tailwindcss alpinejs prettier prettier-plugin-tailwindcss npm-run-all
  • tailwindcss : for TailwindCSS
  • alpinejs : for Alpine
  • prettier : code formatter for HTML/CSS/JavaScript
  • prettier-plugin-tailwindcss : code formatter for TailwindCSS
  • npm-run-all : run NPM scripts in sequential or in parallel

hat001

Prettier

hat014

WebStorm -> Preferences -> Language & Frameworks -> Prettier

  • Prettier package : WebStorm will get a path automatically after installing Prettier
  • Rule for files : add html for Prettier to work with TailwindCSS
  • On Reformat Code action : run Prettier with the default Reformat code action
  • On save : run Prettier on save

After checking On Reformat Code action and On save, Prettier works as the default code formatter instead of WebStorm internal formatter

TailwindCSS Config

$ npx tailwindcss init

Use Tailwind CLI to generate default tailwind.config.js.

hat002

tailwind.config.js

module.exports = {
  content: ["content/**/*.md", "layouts/**/*.html"],
  theme: {
    extend: {},
  },
  plugins: [],
};

Line 2

content: ["content/**/*.md", "layouts/**/*.html"],

Purge unused CSS by specified file extensions.

hat003

CSS

input.css

@tailwind base;
@tailwind components;
@tailwind utilities;
  • Add index.css on the root folder of project
  • Tailwind CLI transpiles input.css to output.css

hat004

Hugo Config

config.json

{
  "baseURL": "http://example.org/",
  "languageCode": "en-us",
  "title": "My New Hugo Site",
  "minify": {
    "tdewolff": {
      "html": {
        "keepWhitespace": false
      }
    }
  }
}

keepWhitespace : Hugo keeps white space by default. We have to set it to false to minimize white space on HTML

hat005

Layout

layouts/index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="alpine.js" defer></script>
    <link rel="stylesheet" href="output.css" />
    <title>HATstack</title>
  </head>
  <body>
    <div class="text-4xl text-red-700">Hello HATstack</div>
    <div x-data="{ count: 0 }">
      <button
        class="rounded-lg bg-gray-200 px-3 py-1 text-gray-800"
        @click="count++"
      >
        +
      </button>
      <span x-text="count" />
    </div>
  </body>
</html>

Line 6

<script src="alpine.js" defer></script>

Only reference the local path of Alpine so that we can run Hugo locally without an internet connection.

Line 7

<link rel="stylesheet" href="output.css" />

Link CSS file to output.css which is transpiled by Tailwind CLI.

Line 11

<div class="text-4xl text-red-700">Hello HATstack</div>

Use TailwindCSS utilities for HTML.

Line 12

<div x-data="{ count: 0 }">
  <button
    class="rounded-lg bg-gray-200 px-3 py-1 text-gray-800"
    @click="count++"
  >
    +
  </button>
  <span x-text="count" />
</div>

Classical counter implemented by Alpine.

hat006

NPM Config

package.json

{
  "scripts": {
    "dev:css": "npx tailwindcss -i input.css -o static/output.css -w",
    "dev:alpine": "cp node_modules/alpinejs/dist/cdn.js static/alpine.js",
    "dev:hugo": "hugo server",
    "dev": "run-p dev:*",
    "build:css": "NODE_ENV=production npx tailwindcss -i input.css -o static/output.css -m",
    "build:alpine": "cp node_modules/alpinejs/dist/cdn.min.js static/alpine.js",
    "build:hugo": "hugo --cleanDestinationDir --minify",
    "build": "run-s build:*"
  },
  "devDependencies": {
    "alpinejs": "^3.8.1",
    "npm-run-all": "^4.1.5",
    "prettier": "^2.5.1",
    "prettier-plugin-tailwindcss": "^0.1.7",
    "tailwindcss": "^3.0.19"
  }
}

Line 3

"dev:css": "npx tailwindcss -i input.css -o static/output.css -w",

Use Tailwind CLI to build CSS under development mode :

  • -i input.css : use input.css as the source CSS file
  • -o static/output.css : use output.css as the target CSS file
  • -w : watch for changes and rebuild as needed

Line 4

"dev:alpine": "cp node_modules/alpinejs/dist/cdn.js static/alpine.js",

Copy Alpine from node_modules to static folder.

Line 5

"dev:hugo": "hugo server",

Run web server by Hugo.

Line 6

"dev": "run-p dev:*",

run-p : run all dev:* in parallel under development mode.

Line 7

"build:css": "NODE_ENV=production npx tailwindcss -i input.css -o static/output.css -m",

Use Tailwind CLI to build CSS under production mode :

  • -i input.css : use input.css as source CSS file
  • -o static/output.css : use output.css as target CSS file
  • -m : minify target CSS file

Line 8

"build:alpine": "cp node_modules/alpinejs/dist/cdn.min.js static/alpine.js",

Copy minimized Alpine from node_modules to static folder.

Line 9

"build:hugo": "hugo --cleanDestinationDir --minify",

Build HTML/CSS/JavaScript for production.

  • cleanDestinationDir : clean up the public folder before building the site
  • minify : remove whitespace characters, resulting in smaller file sizes that will make the site download faster for our visitors

Line 10

"build": "run-s build:*"

run-s : run all build:* in sequential under production mode.

hat007

Development Mode

$ npm run dev

Start web server under development mode.

hat008

TailwindCSS and Alpine with Hugo are enabled successfully under development mode.

hat009

HTML is not minimized under development mode.

hat010

Production Mode

$ npm run build
$ serve public

Build HTML/CSS/JavaScript with minifier under production mode.

hat011

TailwindCSS and Alpine with Hugo are enabled successfully under production mode.

hat012

HTML is minimized under production mode.

hat013

Conclusion

  • It’s not too difficult to integrate HATstack with Hugo. With Alpine and TailwindCSS, we can start to create templates by declarative style directly in HTML
  • Minimizing HTML is provided by Hugo. We don’t have to use other packages