Thu Mar 7, 2019 - 7 min.

Table of Contents generated with DocToc

This page is the documentation describing how I went about creating this website.

Tools used

To create this website, the Hugo framework for static page generation was used and the site is the being built and hosted on Gitlab Pages.


The Hugo Framework is a framework used for static-page generation written in the Go programming language. It contains all the main features which are standard for static-page generation, like:

  • Content Management
  • Templates
  • Layouts
  • Variables

In all the main aspects it is nearly identical to other similar frameworks (e.g. Jekyll). The only functional difference (apart from different Templating languages) is that Hugo doesn’t provide support for plugins, like Jekyll does. However, this does not really affect our work on this page, since Jekyll plugins usually don’t work in statically generated pages.

GitLab Pages

GitLab, like other git providers (such as GitHub), provide free website hosting for users and their repositories, so that they can create pages for their projects or portfolios. GitLab’s hosting goes by the name of GitLab Pages. It provides * domains for their users and their repositories.

Since GitLab is a full DevOps toolkit, it also provides CI/CD (Continuos Integration/Continuos Delivery) Pipelines, which can be set up to run, when a branch in a repository is updated. Leveraging this functionality, we can easily integrate Hugo with GitLab Pages (more on that later on).


This documentation will assume, that all the necessary tools are already installed correctly and present on the machine. If you want to know, how to install any of the tools used, there will be links to their pages/repositories where this information should be present.

Creting a new Hugo Website

To create a new site in hugo, we will run this command:

  hugo new site <site-name>

This will create a new repository with a config file and the directory structure which Hugo uses. It will also create a new default content archetype (a template for the front matter of the markdown files created using the hugo new command.


This website contains 5 different sub-pages which have unique layouts, namely:

  • Home Page - This page contains a general welcome message, as well as a list of 10 most recent posts
  • List of Posts - This page shows a chronological list of all posts published on this page, with some info about each post.
  • Single Post/Page View - The contents of a specific post, with links to previous and next posts as well as metadata, such as tags
  • About Page - A quick page about me, who I am, social links and a list of technologies I’ve written about.
  • Project Documentation - This page, the documentation about the process of creating this blog.

Designing Layouts

This part of the documentation will touch upon the different Variables and Functions of the Hugo Framework, which were used to create each layout.

Home Page

This page renders the message specified in the content/ file and then uses a composed filter statement, which looks like this:

  {{ range first 10 (where .Pages "Section" "posts") }}

to pull the latest 10 pages from the .Pages variable of the site from the section posts. It the uses Content View Templates for the li element to render the list of posts. This is something similar to a partial template, but it’s tied to a specific HTML element and content type. (For more info, see:

List of Posts

On this page, all the pages in the content/posts directory are selected and put into a list, which utilises the same Content View Template as the Home Page. This template takes the .Date and .ReadingTime variables of each post and shows them for each post. It also accesses the Taxonomy (Hugo equivalent of the Jekyll’s Collection concept) of tags and adds little badges to each post, which link to a list of all posts with said tag.

Single Post

Apart from obviously rendering the content of the Markdown file of the specif post, this page also accesses the .Date, .ReadingTime variables, as well as the tags taxonomy. It also uses a with statement to access the context of the previous and next posts. The statement looks like this:

  {{ with .PrevInSection }}

for the Previous post and like this:

  {{ with .NextInSection }}

for the Next post. This context switch allows us to add links to the previous and next posts in the posts Section, which are placed on the bottom of the post page.

About Page

This page shows at first a centered avatar image pulled from my GitLab profile, underneath which there are my social links and then the rendered about/ Markdown file. Following this brief description is card deck, titled “Technologies I Work With”. This card deck pull the information from a technologies Taxonomy, from where it pulls all the Terms (keys) present in the articles, displays the number of posts for each of the Terms, as well as provides a link to the Term list page, which shows all posts related to said Term.

The code used to display this list will be similar to something along the lines of this example:

  {{range $name, $value := .Site.Taxonomies.technologies}}
      {{ $name | title }} //$name of the Term/ technology, the 'title' function capitalizes it
      {{ .Count }} //the count of all Pages in the WeightedPages list returned as $values

Design and CSS

To create the design of this web-page I used Bootstrap and Font Awesome Icons. Their Usage can be seen in all the layout files in the layouts/ directory. There was only one place, where custom styles were used and that was the “Older Posts” button on the Home page. The specific style used can be found in static/css/main.css.

Plugins and Hooks

This site uses the Chroma syntax highlighter, which is natively supported by Hugo, to highlight all the code snippets present on this page.

It also provides the built-in RSS Feed, which is available in the footer of the page.

Finally, this page uses doctoc to generate Tables of Content for all the markdown files on the page. The repository has a set up pre-commit hook, which automatically runs doctoc against all Markdown files in the repository.

Integrating with GitLab Pages

To integrate this Hugo website with GitLab Pages, we need to create a GitLab CI configuration, which will build and deploy our site every time we commit some changes to the remote repository. We do this by creating a new .gitlab-ci.yml in the root directory. The configuration will look like this:

  image: monachus/hugo


    - hugo
      - public
    - master

This file will tell GitLab to run the hugo script from the specified image on the whole repository and deploy the public/ directory, which will contain the built static site, but only against the master branch.

Jekyll and GitHub Pages Equivalent

In this section, I will shortly summarize, how I would go about creating a similar website, only using Jekyll and GitHub Pages.

Most of the high concepts are similar between both of the frameworks. Hugo has a bit more stuff built-in, which Jekyll provides as plugins (e.g. Syntax Highlighting, Pagination, RSS Feeds, etc.) and some things have different nomiclature (Taxonomies - Collections, or Templates - Layouts).

Apart from those things, the slight difference in the Templating languages and the fact that one is written in Ruby and one in Go (which makes very little difference, since both operate similarly.), the process of creating pages, using variables, adding Front Matter, specifying Taxonomies/Collections is pretty much identical.

The process of integrating with GitHub Pages and Jekyll is even easier than GitLab and Hugo. You simply push into a correctly named repository and GitHub does the hard work for you.