a short introduction to Hugo

Recently Andreas has migrated our website from Wordpress to Hugo and after that i have written this small introduction for a TLUG workshop. The article describes the basic installation and configuration steps plus the creation of the first content.

What and why is hugo?

  • static website generator that
    • supports separation of content and code with themes
    • renders your content into static html pages with css and optional javascript integration
    • can be fully automated with the tool (Ansible, Jenkins, Helm etc.) of your choice
    • is written in Go and released as static binary
  • to simplify webserver infrastructures by avoiding
    • databases like MySQL
    • server side program languages like PHP
    • caching components like Redis


brew install hugo


  • create the website folder structure
  • choose a theme and create the folder for it
  • download and extract the theme into the folder
hugo new site --source ./ test.batchworks.de
mkdir -p test.batchworks.de/themes/hugo-geekdoc/
curl -sL https://github.com/thegeeklab/hugo-geekdoc/releases/download/v0.19.1/hugo-geekdoc.tar.gz | tar -xz -C test.batchworks.de/themes/hugo-geekdoc/
  • extend the hugo configuration (config.toml) with the desired options
  • this also includes some theme related options
    • Theme options are not namespaced. This makes it sometimes hard to switch between them
baseurl = "http://test.batchworks.de/"
languageCode = "en-us"
title = "test.batchworks.de"
theme = "hugo-geekdoc"

  posts = "/:title/"
  page = "/:slug/"

## geekdoc theme settings

# Required to get well formatted code blocks
pygmentsUseClasses = true
pygmentsCodeFences = true
disablePathToLower = true
enableGitInfo = false

      unsafe = true
    startLevel = 1
    endLevel = 9

  author = "authors"
  tag = "tags"

## geekdoc theme settings end

# Theme variables
  # Site author
  author = "Birk Bohne"

  geekdocBreadcrumb = false

  # Format dates with Go's time formatting
  date_format = "Mon Jan 02, 2006"


the first page

  • Hugo pages or posts are written in Markdown with some theme specific header config
  • create the first page in the test.batchworks.de/content/_index.md file and add the content
title: Welcome to the test site
geekdocDescription: This is the start page.
weight: 10

# The start page

Welcome to the start page

local test with hugo

  • start hugo in server mode to locally render the content
hugo server --source test.batchworks.de/ --baseUrl http://localhost

Start building sites …
hugo v0.88.1+extended darwin/amd64 BuildDate=unknown

                  | EN
  Pages            |   7
  Paginator pages  |   0
  Non-page files   |   0
  Static files     | 105
  Processed images |   0
  Aliases          |   2
  Sitemaps         |   1
  Cleaned          |   0

Built in 31 ms

update the first page

  • paste the content of the README.md below the theme config section in the test.batchworks.de/content/_index.md file
  • check your browser

content structure with folders

  • create a test.batchworks.de/content/sub/ folder and an _index.md file in it
  • add the content
title: Sub content
geekdocDescription: focus on other topics
weight: 10

the sub page
  • check your browser again

add charts

  • the Geekdoc theme supports Mermaid for the rendering of different chart types
  • create a test.batchworks.de/content/sub/mermaid.md file
  • add the content
title: Mermaid charts
geekdocDescription: render charts with mermaid markup code
weight: 10

{{< mermaid class="text-center">}}
flowchart TD
    A[Start] --> B{Is it?};
    B -->|Yes| C[OK];
    C --> D[Rethink];
    D --> B;
    B ---->|No| E[End];
{{< /mermaid >}}
  • check your browser again

use structured data sources

  • Hugo can read data structures for instance from JSON or YAML
  • this can be used to populate tables or other html structures
  • First we have to create the html template
    • create a test.batchworks.de/layouts/shortcodes/data_table.html file
    • add the content
{{ $arg0 := .Get 0 }}
{{ $data := index .Site.Data.content $arg0 }}
{{ $.Scratch.Set "count" 0 }}


    {{ range $datacontent := $data }}
            <td>{{ $datacontent.name }}</td>
            <td>{{ $datacontent.function }}</td>
    {{ end }}
  • Next we have to create the data source
    • create a test.batchworks.de/data/content/data.yaml file
    • add the content
- name: "json"
  function: "read JSON"
- name: "csv"
  function: "read CSV"
  • Now we create the page that should render the table
    • create a test.batchworks.de/content/sub/table.md file
    • add the content
title: Data tables
geekdocDescription: render tables
weight: 20

## Data sources

{{< data_table "data" >}}
  • check your browser again

Render the site

  • use Hugo to render the static pages
  • they can than be served by the webserver of your choice without further dependencies
    • create a target and a tmp dir
    • call hugo to render the pages
mkdir -p tmp/ www/
hugo --source ${PWD}/test.batchworks.de/ --cacheDir ${PWD}/tmp --destination ${PWD}/www --baseURL http://test.batchworks.de

Further steps

  • maintain the Hugo config and content in a source code management system
  • maintain the rendered pages in an SCM too
  • upload the www folder to your web server
  • use automation tools like Ansible, Jenkins etc. to automate the workflow