Module Guide

Do you want to create and share your creative HB modules? Here is everything you want to know.

Example Functionalities

Source code.

Let’s get started with a hello example, which:

  • Appends attributes on <html> and <body>.
  • Using hooks to include custom HTML markup, such as meta tags, CSS and JS.
  • Generates greeting messages on HTML pages, and style/modify it with SCSS/TypeScript.

Preparations

  • An HB site for testing your module, you could use the starter theme if you don’t have one yet.
  • Familiar with Hugo development.
  • Build tools installations.

Initial Module

First of all, create and initial a module.

1mkdir hello && cd hello
1git init
1hugo mod init example.com/vendor/hello

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

Set up a HB Site

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

Import the Local Module

Firstly, we need to import the local hello module into site’s configuration:

hugo.toml

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

hugo.yaml

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

hugo.json

1{
2   "module": {
3      "imports": [
4         {
5            "path": "example.com/vendor/hello"
6         }
7      ]
8   }
9}

And then mapping the module to local path in site’s go.mod.

1replace example.com/vendor/hello => /path/to/hello

The /path/to/hello is the file path of the hello module, both of relative path and absolute path are valid.

Start the Testing Site

1hugo server --gc --disableFastRender

Module Configuration File

Back to the module, create a module configuration file.

hugo.toml

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

hugo.yaml

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

hugo.json

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

It declared that the github.com/hbstack/hb module is required.

It’s time to start implementing the functionalities.

Append Attributes on <html> and <body>

To add additional HTML attributes by appending 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 via partials.

If everything is OK, the HTML source code looks like follows:

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

Using Hooks

This example uses only a few hooks, all available hooks could be found on our docs and HugoPress’s built-in hooks.

Please note that the context of hook partials is different than regular partial, see hooks context.

Generate Stuff on <head>

There are two built-in hooks for putting custom stuff on <head>: head-begin and head-end, which used to generate meta tags, include stylesheet and so on.

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, disable the cacheable if the template contains dynamic data.

And then create the corresponding templates.

Now the pages have the following meta tags.

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

Generates the Greeting Message

Finally, create greeting messages on the top of pages.

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

hugo.yaml

1params:
2  hugopress:
3    modules:
4      hb-vendor-hello:
5        hooks:
6          body-begin:
7            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               }
11            }
12         }
13      }
14   }
15}
layouts/partials/hugopress/modules/hb-vendor-hello/hooks/body-begin.html
1<div class="hb-vendor-hello text-center">Hello!</div>

Now the greeting message will be shown on the top of pages.

Styling Module

You may want to beautify the HTML generated by module with styles, let’s take the greeting message as an example that change the background and color.

To make module flexible, we declare parameters for those styles.

hugo.toml

1[params]
2  [params.hb]
3    [params.hb.vendor_hello]
4      bg = 'blue'
5      color = 'white'

hugo.yaml

1params:
2  hb:
3    vendor_hello:
4      bg: blue
5      color: white

hugo.json

 1{
 2   "params": {
 3      "hb": {
 4         "vendor_hello": {
 5            "bg": "blue",
 6            "color": "white"
 7         }
 8      }
 9   }
10}

And then create the SCSS files.

assets/hb/modules/vendor-hello/scss/variables.tmpl.scss
1$hb-vendor-hello-bg: {{ default "blue" .params.hb.vendor_hello.bg }};
2$hb-vendor-hello-color: {{ default "white" .params.hb.vendor_hello.color }};
assets/hb/modules/vendor-hello/scss/index.scss
1/* purgecss start ignore */
2
3.hb-vendor-hello {
4    background: $hb-vendor-hello-bg;
5    color: $hb-vendor-hello-color;
6}
7
8/* purgecss end ignore */

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

Adding Scripts

Finally, let’s modify the greeting message in JS way.

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}
assets/hb/modules/vendor-hello/js/index.ts
1import * as params from '@params'
2
3document.querySelector('.hb-vendor-hello').innerText = params.vendor_hello.message

Test on Production Mode

The styles used by JavaScript will be removed by PurgeCSS, please checkout the PurgeCSS section for details.

The PurgeCSS gets processed on production mode only, we could preview the module on production mode via:

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

Deployment

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

razonyang
Tuesday, December 3, 2024 Thursday, February 16, 2023