JustToThePoint English Website Version
JustToThePoint en español
JustToThePoint in Thai

A complete hands-on guide to using Hugo

Let’s get started.

Hugo is one of the most popular open-source static site generators written in Go. It is fast, ease of use, and flexible. Hugo supports markdown JustToThePoint, Markdown and LaTeX.

Programming in Hugo

Programming in Hugo

Layouts in Hugo and basic structure

A layout is a page used as a “frame”, “skeleton” or “basic template” to display your content. It consists of all the parts that remain consistent across all of the pages. Hugo uses a layout for the home page, a second one for content pages, and a third one that shows or displays lists of pages.

The main home page layout will live in themes/anawim/layouts/index.html, where anawim is my theme. This file defines the HTML structure or skeleton for the site’s home page:

{{ define "main" }}
<div class="container mx-auto">
    <h1> {{ .Site.Title }} </h1>

{{ .Site.Title }} specifies that we want to pull the title field out of the config.yaml, the main Hugo’s configuration file.

    {{if .Params.subtitle }}
    <h2 class="text-secondary h3"> {{ .Params.subtitle }} </h2>    
    {{ end }}
    <p> {{ .Description }} </p>
    {{ .Content | markdownify }}

The {{ .Content | markdownify }} line displays the content of the page. This content will be in a Markdown document in our content folder, more specifically, in the “scope” or context" that contains the data we want to access. The current context is represented by a dot “.” and the content’s file is a file named _index.md in the content directory. It takes this content and runs it through Hugo’s Markdown processor.

The layouts directory contains all the HTML files that are used for generating HTML from the Markdown files. In other words, they specify how your content will be rendered. The _default directory is the place where Hugo will search for the base page layout file, that is, baseof.html:

<!doctype html>
<!-- prefix="og: http://ogp.me/ns#" is the required prefix for open graph protocol meta tags. -->
<html prefix="og: http://ogp.me/ns#" lang="{{ .Site.Language.Lang }}" >
  <!-- Schema.org provides a collection of shared vocabularies webmasters can use to mark up their pages 
  in ways that can be understood by the major search engines! -->
  <head itemscope itemtype="https://schema.org/WebPage">
    {{- partial "mymeta" . -}}   <!-- SEO: meta tags -->
    {{- partial "head" . -}} <!-- Google Analytics -->
    {{- partial "search-form" . }} <!-- Search with Lunr -->
    {{- partial "navbar" . -}} <!-- Menu, Navbar -->
    {{- block "main" . -}} {{ end }}  
    {{- partial "script-footer" . -}} <!-- Javascript -->
    {{- partial "footer" . -}} <!-- Social Media, Copyright, Privacy Policy and Terms of Use -->
    {{- partial "style" . -}} <!-- Css -->
    {{- partial "search-index.html" . }} <!-- Search with Lunr -->

Observe that we define blocks and partial where we define the different “sections” or “pieces” of our content, e.g., the first two partials (mymeta, head) contain the code that will appear in the HEAD. The dash “-” removes whitespace characters in the output, so we are using it in every partial to reduce the number of blank lines that Hugo generates.

Under the layouts folder, you can see there is a folder called partials. It contains all our partial templates.

There is a “main” block layout. This line looks for this block and pulls its content. It is defined in index.html (site’s home page) and single.html.

list.html is the “frame” or “html template” that Hugo uses to list posts of your site under a particular directory. single.html is the templated used to display a single page.

If you want to write about shortcodes, you need to replace the opening greater-than sign “<” with &lt; or “%” with &#37;.

{{ < img src="../images/best-friends.webp" title=“best-friends” src2="../images/best-friends.jpg" >}}

By default, Hugo replaces two hyphens for a single dash, “–” the solution is this: &hyphen;&hyphen; ‐‐

The same goes with emojis, instead of :star: ⭐️, you use an HTML entity for one of the colons in the emoji code: :star&#58;

If you want that Hugo does not turn &hyphen; into “‐”, you need to replace the ampersand “&” with &amp; e.g., content_new = pattern.sub('&amp;hyphen;&amp;hyphen;', content_new)

 content_new = pattern.sub("&hyphen;&hyphen;", content_new)

I also use this shortcode -spam.html-, htmlEscape returns the given string with the reserved HTML coded escaped:

<span {{ with .Get "style"}} style="{{ . | safeCSS }}"{{ end }}>{{ .Get "text" | htmlEscape }}</span>

First, we use the .Get function to retrieve the style parameter passed to our shortcode (e.g., “color:red;”). The dot’s value is different from the value inside the “with” block, it changes based on context, which is our style in this case. safeCSS declared the provided string as a “safe” CSS string. Next, we retrieve the text parameter and pipe it into htmlEscape.


{{< span style="color:red;" text="&hyphen;" >}}

Result: &hyphen;

Cactus Comments is a federated comment system built on Matrix. It respects your privacy, and puts you in control. The entire thing is completely free and open source.

  1. First, you must have a Matrix account and register your site with Cactus Comments. Using Element, start a new chat with @cactusbot:cactus.chat and type:

      register YOUR-SITE-NAME # e.g., register JustToThePoint

    You should receive a confirmation: Created site YOUR-SITE-NAME for you 🚀

  2. Add a Shortcode: layouts/shortcode/chat.html

      <script type="text/javascript" src="https://latest.cactus.chat/cactus.js"></script>
      <link rel="stylesheet" href="https://latest.cactus.chat/style.css" type="text/css">
      <div id="comment-section"></div>
        node: document.getElementById("comment-section"),
        defaultHomeserverUrl: "https://matrix.cactus.chat:8448",
        serverName: "cactus.chat",
        siteName: "<YOUR-SITE-NAME>",
        commentSectionId: "{{ index .Params 0 }}"
  3. The last step is to add the following code at the end of your posts:

        {{< chat cactus-comments >}}
  4. Another option is to create a partial (/layout/partials/chat.html) with the following code:

        <script type="text/javascript" src="https://latest.cactus.chat/cactus.js"></script>
        <link rel="stylesheet" href="https://latest.cactus.chat/style.css" type="text/css">
        <div id="comment-section"></div>
          node: document.getElementById("comment-section"),
          defaultHomeserverUrl: "https://matrix.cactus.chat:8448",
          serverName: "cactus.chat",
          siteName: "JustToThePoint.com",
          commentSectionId: "cactus-comments"
  5. And call this partial from baseof.html:

        {{- block "main" . -}} {{ end }}
        {{- partial "chat" . }}

Basic configuration.

Let’s open config.yaml:

baseURL: https://justtothepoint.com/ # url address of the website | required
theme: "anawim"
pygmentsUseClasses: true # We are going to use a style sheet for highlighting. 
pygmentsCodefences: true # It enable syntax highlighting in code fences with a language tag (html, python, css, json, md, etc.) in markdown: ``` html [ my code html ] ``` 
PygmentsStyle: "monokai"
languageCode: en-us
title: JustToThePoint  # The title of the site.
copyright: "Copyright © 2022 JustToThePoint. All rights reserved." # Copyright notice for your site, typically displayed in the footer.
googleAnalytics: YourCodeHere # It enables Google Analytics by providing your tracking ID.
defaultContentLanguage: en # Content without language indicator will default to this language.
enableEmoji: true # It enables Emoji emoticons support.
enableRobotsTXT: true # It enables generation of robots.txt file. It tells search engine crawlers which URLs the crawler can access on your site.
assetDir: "assets/"

Without adding a single line to our config file, Hugo will automatically create taxonomies for tags and categories. I don’t want Hugo to create any taxonomies, so I set disableKinds in config.yaml as follows:

- taxonomy
- term
markup: # Configure Markup
    goldmark: # Goldmark is the default library used for Markdown.
            footnote: true # It enables footnote. 😄
            unsafe: true # By default, Goldmark does not render raw HTML.
    highlight: # This is the highlight configuration. Hugo uses Chroma as its code highlighter.
        codeFences: true # It enables syntax highlighting with GitHub flavored code fences: ``` html [ my code html ] ``` By default, Highlighting is carried out via the built-in shortcode highlight.
        guessSyntax: true # It tries to do syntax highlighting on code fenced blocks in markdown without a language tag.
        lineNos: false # It configures line numbers.
        tabWidth: 4
    author: Máximo Núñez Alarcón, Anawim
    og_image: https://www.justtothepoint.com/myImages/logotipoMagotipoCabecera.png
    description: Free bilingual e-books, articles, resources, and videos to help your child and your entire family succeed, develop a healthy lifestyle, and have a lot of fun.

            facebook: "https://www.facebook.com/nmaximo7"
            github: "https://github.com/nmaximo7"
            twitter: "http://Twitter.com/justtothepoint"
            instagram: "http://instagram.com/justtothepoint"
            linkedin: "https://www.linkedin.com/in/justtothepoint"
            youtube: "https://youtube.com/justtothepoint"

Let’s use NPM as a Build Tool with Hugo

NPM is a package manager for JavaScript. It consists of a command line client (npm) and an online database of public and paid-for private packages, called the npm registry.

Node.js (Node) is a run time open source development platform. It allows us to write JavaScript code that runs directly in a computer process instead of in a browser, so it is used to write server-side applications with access to the operating system, file system, and everything else required to build fully-functional applications.

  1. Initialize the project: npm init (project’s name, initial version, description, etc.) It will generate a package.json file in the current directory. A package.json file is your project’s manifest. It includes the packages and applications it depends on, information about its unique source control, and specific metadata.

  2. You can install modules with npm install myModule or install modules and save them to your package.json as a dependency: npm install –save-dev npm-check. We are going to install npm-check and hugo-installer.

    npm-check checks for outdated, incorrect, and unused dependencies. hugo-installer installs Hugo into your repository: npm install hugo-installer –save-dev

  3. Edit the package.json file. JSON does not support comments.

  "name": "justtothepoint", // The name of the project.
  "version": "1.0.0", // The version of the project.
  "description": "Free resources, bilingual e-books and videos to help your child and your entire family succeed, develop a healthy lifestyle, and have a lot of fun.", // The description of the project
  "main": "index.js",
  "scripts": {
    "dev": "exec-bin node_modules/.bin/hugo/hugo server --gc --disableFastRender", 
    // It runs Hugo's webserver: -gc remove unused cache files after the build; --disableFastRender enables full re-renders on changes.
    "build": "exec-bin node_modules/.bin/hugo/hugo --gc -cleanDestinationDir --minify", 
    // --cleanDestinationDir removes files from destination not found in static directories. --minify reduces CSS code size and make your website load faster.
    "prebuild": "exec-bin node_modules/.bin/hugo/hugo --gc --cleanDestinationDir",
    "npm-check": "npm-check -u",
    "start": "exec-bin node_modules/.bin/hugo/hugo server -d-disableFastRender --gc --renderToDisk --cleanDestinationDir", 
    // --renderToDisk serve all files from disk. Please notice that the default is to serve all files from memory.
    "postinstall": "hugo-installer --version otherDependencies.hugo --extended --destination node_modules/.bin/hugo"
    // hugo-installer is recommended as part of our postinstall hook within our project's package.json. It installs Hugo into the repository. --destination is the path to the folder into which the binary will be put. --extended download the extended version of Hugo.
  "author": "Máximo Núñez Alarcón, Anawim", // The author of the project.
  "license": "ISC", // The license of the project.
  "devDependencies": {
    "npm-check": "^5.9.2"
  "dependencies": {
    "exec-bin": "^1.0.0",
    "hugo-installer": "^3.1.0"
  "otherDependencies": {
    "hugo": "0.96.0"

  1. Credits: geekthis, Hugo Footnotes and Citations ↩︎

Bitcoin donation

JustToThePoint Copyright © 2011 - 2022 Anawim. ALL RIGHTS RESERVED. Bilingual e-books, articles, and videos to help your child and your entire family succeed, develop a healthy lifestyle, and have a lot of fun.

This website uses cookies to improve your navigation experience.
By continuing, you are consenting to our use of cookies, in accordance with our Cookies Policy and Website Terms and Conditions of use.