Module Guide

In this article, you will learn how to create a HB module.

Let’s take hello as example, which:

  1. Generates <html>, <body> attributes.
  2. Generates meta tags, or even import external CSS and JS.
  3. Generates greeting messages on HTML pages, and style it with CSS.
  4. Generates greeting messages on browser console via JS.

Initial Module

First of all, create and initial a module.

1mkdir hello && cd hello
2
3git init
4
5hugo mod init github.com/vendor/hello

Replace the module path github.com/vendor/hello as your own, the vendor is your username or organization name.

Import the Local Module

It’s recommended importing the local module into your site for developing.

  1. Import the module into your site’s configuration.

hugo.toml

1[module]
2[[module.imports]]
3  path = 'github.com/vendor/hello'

hugo.yaml

1module:
2  imports:
3  - path: github.com/vendor/hello

hugo.json

1{
2   "module": {
3      "imports": [
4         {
5            "path": "github.com/vendor/hello"
6         }
7      ]
8   }
9}
  1. And then mapping the module to local path in site’s go.mod.
1replace github.com/vendor/hello => ../hello

The ../hello is a relative path, please modify it according to your own environment.

Module Configuration File

Create a module configuration file will be used in the rest steps.

hugo.toml

1[module]
2[[module.imports]]
3  path = 'github.com/razonyang/hb'

hugo.yaml

1module:
2  imports:
3  - path: github.com/razonyang/hb

hugo.json

1{
2   "module": {
3      "imports": [
4         {
5            "path": "github.com/razonyang/hb"
6         }
7      ]
8   }
9}
1[[module.imports]]
2path = "github.com/razonyang/hb"

It’s time to start implementing the functionality, let’s generate some HTML attributes and markup on pages.

Generate <html> and <body> Attributes

To enable the additional <html> attributes by setting the following configuration.

hugo.toml

1[params]
2  [params.hugopress]
3    [params.hugopress.modules]
4      [params.hugopress.modules.hb-vendor-hello]
5        [params.hugopress.modules.hb-vendor-hello.attributes]
6          [params.hugopress.modules.hb-vendor-hello.attributes.body]
7            cacheable = true
8          [params.hugopress.modules.hb-vendor-hello.attributes.document]
9            cacheable = true

hugo.yaml

1params:
2  hugopress:
3    modules:
4      hb-vendor-hello:
5        attributes:
6          body:
7            cacheable: true
8          document:
9            cacheable: true

hugo.json

 1{
 2   "params": {
 3      "hugopress": {
 4         "modules": {
 5            "hb-vendor-hello": {
 6               "attributes": {
 7                  "body": {
 8                     "cacheable": true
 9                  },
10                  "document": {
11                     "cacheable": true
12                  }
13               }
14            }
15         }
16      }
17   }
18}

The cacheable flag caches the attributes to improve the build performance, disable it if the attributes contain dynamic data.

And then define the additional attributes.

1// layouts/partials/hugopress/modules/hb-vendor-hello/attributes/document.html
2{{- return dict 
3  "data-hello" "foo"
4-}}
5
6// layouts/partials/hugopress/modules/hb-vendor-hello/attributes/document.html
7{{- return dict 
8  "data-hello" "bar"
9-}}

If everything is OK, the <html> tag looks like:

1<html ... data-hello="foo" ...>
2  <body ... data-hello="bar" ...>
3  </body>
4</html>

Generates Meta Tags

There are two places for meta tags to put into: head-begin and head-begin.

Append the following configuration to enable it.

hugo.toml

1[params]
2  [params.hugopress]
3    [params.hugopress.modules]
4      [params.hugopress.modules.hb-vendor-hello]
5        [params.hugopress.modules.hb-vendor-hello.hooks]
6          [params.hugopress.modules.hb-vendor-hello.hooks.head-begin]
7            cacheable = true
8          [params.hugopress.modules.hb-vendor-hello.hooks.head-end]
9            cacheable = true

hugo.yaml

1params:
2  hugopress:
3    modules:
4      hb-vendor-hello:
5        hooks:
6          head-begin:
7            cacheable: true
8          head-end:
9            cacheable: true

hugo.json

 1{
 2   "params": {
 3      "hugopress": {
 4         "modules": {
 5            "hb-vendor-hello": {
 6               "hooks": {
 7                  "head-begin": {
 8                     "cacheable": true
 9                  },
10                  "head-end": {
11                     "cacheable": true
12                  }
13               }
14            }
15         }
16      }
17   }
18}

Same as attributes, remove the cacheable if the meta tags template contains dynamic data.

And then create the corresponding templates.

1// layouts/partials/hugopress/modules/hb-vendor-hello/hooks/head-begin.html
2<meta name="hello" content="head-begin">
3
4// layouts/partials/hugopress/modules/hb-vendor-hello/hooks/head-end.html
5<meta name="hello" content="head-end">

Now the pages have the following meta tags.

1<meta name="hello" content="head-begin">
2<meta name="hello" content="head-end">

Generates Greeting Messages Markup

Finally, create greeting messages on the beginning and ending.

Configuration as following.

hugo.toml

1[params]
2  [params.hugopress]
3    [params.hugopress.modules]
4      [params.hugopress.modules.hb-vendor-hello]
5        [params.hugopress.modules.hb-vendor-hello.hooks]
6          [params.hugopress.modules.hb-vendor-hello.hooks.body-begin]
7            cacheable = true
8          [params.hugopress.modules.hb-vendor-hello.hooks.body-end]
9            cacheable = true

hugo.yaml

1params:
2  hugopress:
3    modules:
4      hb-vendor-hello:
5        hooks:
6          body-begin:
7            cacheable: true
8          body-end:
9            cacheable: true

hugo.json

 1{
 2   "params": {
 3      "hugopress": {
 4         "modules": {
 5            "hb-vendor-hello": {
 6               "hooks": {
 7                  "body-begin": {
 8                     "cacheable": true
 9                  },
10                  "body-end": {
11                     "cacheable": true
12                  }
13               }
14            }
15         }
16      }
17   }
18}
1// layouts/partials/hugopress/modules/hb-vendor-hello/hooks/body-begin.html
2<div class="hb-vendor-hello text-center py-2">Greeting from body begin.</div>
3
4// layouts/partials/hugopress/modules/hb-vendor-hello/hooks/body-end.html
5<div class="hb-vendor-hello text-center py-2">Greeting from body end.</div>

The hooks like head-begin, head-end, body-begin and body-end can also used to import external CSS, JS or other stuff.

  1. It’s allowed that defines other hooks other than HugoPress built-in hooks, such as the built-in header, footer, blog and docs modules.

Module Style

Next, let’s change the background color of the greeting messages.

hugo.toml

1[params]
2  [params.hb]
3    [params.hb.vendor_hello]
4      bg = 'green'

hugo.yaml

1params:
2  hb:
3    vendor_hello:
4      bg: green

hugo.json

1{
2   "params": {
3      "hb": {
4         "vendor_hello": {
5            "bg": "green"
6         }
7      }
8   }
9}

In order not to conflict with the Hugo modules and the built-in HB modules, it is recommended that the parameters start with hb.[vendor]_[module].

Create the SCSS files.

1// assets/hb/modules/vendor-hello/scss/variables.tmpl.scss
2$hb-vendor-hello-bg: {{ default "blue" .params.hb.vendor_hello.bg }};
3
4// assets/hb/modules/vendor-hello/scss/index.scss
5.hb-vendor-hello {
6    background: $hb-vendor-hello-bg;
7    color: var(--#{$prefix}white);
8}

As the code shown, we declared a SCSS variable (reading from the configuration).

Restart the Hugo server to ensure loading the SCSS files fully.

Module JavaScript

hugo.toml

1[params]
2  [params.hb]
3    [params.hb.vendor_hello]
4      message = 'Hello world'

hugo.yaml

1params:
2  hb:
3    vendor_hello:
4      message: Hello world

hugo.json

1{
2   "params": {
3      "hb": {
4         "vendor_hello": {
5            "message": "Hello world"
6         }
7      }
8   }
9}
1// assets/hb/modules/vendor-hello/js/index.ts
2import * as params from '@params'
3
4console.log(params.vendor_hello.message)

The browser console will show the message Hello world.

Test on Production Mode

The PurgeCSS will be processed on production mode, we could preview it on production mode via:

1hugo server -e production --minify --gc --renderToDisk -b http://localhost:1313 -p 1313

Deployment

Once the module is done, we can publish it by pushing it to your git providers, and then remove the mapping from go.mod.