Host a GitHub Page with Hugo #
This is a brief tutorial on how to set up a GitHub page with Hugo as a static content generator. It’s a simple and easy solution to maintain a personal website and blog. Especially if your a coder and used to working with git and the command line.
Prerequisites
The following topics are mandatory and won’t be covered in this tutorial:
- A working installation of Hugo
- Basic git knowledge
- A GitHub account
- Markdown syntax
1 Hugo #
Hugo is one of the key components for this project.
Hugo is a open-source static site generator. Once installed it can be used inside the command line to build static websites from markdown files. The tool comes with a powerful theme engine and is customizable using templates. Hugo builds the mandatory file system during project creation and is later configured using a config.toml
file. Hugo lets you create your content as pure markdown files, extend them with a file header and publish them directly to your website, only from the command line. In combination with the right theme this is all you need, if you know your way around git and the terminal, to run your website. I find it a lot easier to deal with, then with wordpress and co.
Hugo has a lot more to offer, than this tutorial covers. For further reading, check the projects homepage.
2 Project creation #
Before we can start configuring, styling and filling our page with content, we need to build a new Hugo project and set up the connection with github pages.
2.1 Github setup #
A project like this consists of two github repositories. One so called production
repo, which contains the static files, github pages will then host our site of, and one repository, I will call the working
repo from now on, cause mine is named this way. If you’re building a portfolio or some other kind of page feel free to use another name. The second repository will contain the actual code and configuration for the site. The working
repo will later be linked by a submodule to the production repo, to push changes to the site directly to the live version. Go ahead an create two public repositories with no initial content:
- create
working
repo and name it as you like - create
production
repo and name it<username>.github.io
Since we are using a personal github page for our project, the name of the production
repo has to be <github_username>.github.io
. Each account is limited to a single personal page, but each repo to a project can have its own site (the setup process is a little bit different though).
Next we have to clone the remote repository to our local drive. Since the root folder of the repo contains everything we will need, we can directly put it into our home directory like I did, since I will have to access it a lot in the future. My repo is called website
so I’ll go along with this name for the purpose of this tutorial.
Clone repository to local drive and cd into it:
1~ $ git clone https://github.com/<username>/website.git
2~ $ cd website
After cloning we will checkout main
branch, add README.md
and .gitignore
and push the changes to origin:
1# Create main branch an switch to it
2~/website $ git checkout -b main
3# Create files - Edit them now if you like
4~/website $ touch README.md
5~/website $ touch .gitignore
6# Stage and commit changes
7~/website $ git add .
8~/website $ git commit -m 'initial commit'
9# Push changes to origin/main
10~/website $ git push origin main
We now have established a local version of our project folder and can continue with building the Hugo project and files.
2.2 Create Hugo project #
Let’s start by running hugo new site
in our root folder:
1# Hugo command to build a new project
2hugo new site <website-name> // named code-monkey for this tutorial
The hugo new site
command did all the heavy lifting for us, by creating a lot of boiler plate code, and the mandatory file structure, in order for hugo to work properly. The project structure should look something like this right now:
.
└── /website (git repository)
├── /code-monkey
| ├── /content
| └── lots of other Hugo files ...
└── .git_files
2.3 Establish repository connection #
When we’re ready to build a version of our site into static HTML data, Hugo will put the resulting files into a folder called public
inside our root directory. If we now add a submodule to our production repo inside this public folder, we will automatically update the live version of our site, when we commit changes to the submodule.
To add the submodule to the public folder, go to the command line and type the following:
1# Create submodule from main branch of repo and clone it to the public folder
2~/website $ git submodule add -b main <username>.github.io public
We now have a working connection between the two repositories, which enables us to update the site from our working
repo.
3 Configure Hugo #
The next step is to configure the pre build Hugo project, to make it our own. The first step of this process would be to choose a theme.
3.1 Choosing a theme #
Choosing a theme is a key part of the creation process. I wanted to build a wiki style page, where I could easily manage content on different topics, present it in a clean and structured way, as well as beeing able to search the site for specific content. A blog to accompany the more in depth articles was also mandatory. The Hugo Themes page is a wonderful resource on all available themes. I went with Hugo - Books, cause it fits everything I need and I also liked the design a lot.
To install a Hugo theme, navigate to the themes github repo and copy its link to clone it into your project. This approach works for most themes. Otherwise the themes documentation will point out how to install it. It seems to be best practice to submodule the theme rather than simply cloning it. Some themes may have different installing instructions specified in their documentation.
1~ /website cd code-monkey
2~ //code-monkey $ git submodule add https://github.com/alex-shpak/hugo-book.git themes/book
This creates a submodule of the desired theme inside our blog repo. If the theme is later updated, we can simply pull changes from the original repository of the theme.
3.2 Configuration #
The configuration of Hugo heavily depends on the theme used. In this article I will cover the configuration of the Books theme. Please see the documentation of your chosen theme for further instructions.
Basic configuration #
Hugo is configured using a config
file in the root directory. It is possible to divide the configuration over multiple files, by using a config
folder, but this will not be covered in this tutorial. For a more comprehensive guide check the official
documentation.
The config
file can be in either .toml
, .yaml
or .json
. The example below shows the syntax of the first two options.
Hugo config.yaml
syntax:
1baseURL: base URL of live version
2title: Website Name
3author: Website Author
4keywords: ["keyA", "keyB", "etc."]
5theme: theme-name
6
7params:
8 paramName: value
Hugo config.toml
syntax:
1baseURL = base URL of live version
2title = Website Name
3author = Website Author
4keywords = ["keyA", "keyB", "etc."]
5theme = theme-name
6
7[params]
8 paramName: value
Theme configuration #
Some Hugo themes have extensive configuration options. Book on the other hand is luckily quite simple. The following example shows the complete configuration of this website and is annotated with comments for further details:
Book Theme Config
1baseURL: https://abl3t0nnile.github.io/
2title: a Coding Monkey
3author: Gregor Minnemann
4keywords: ["personal", "coding", "computer science", "swift", "python", "markdown", "blog", "abl3t0nnile"]
5theme: book
6
7# Book configuration
8disablePathToLower: true
9enableGitInfo: true
10
11# Needed for mermaid/katex shortcodes
12markup:
13 goldmark:
14 renderer:
15 unsafe: true
16 tableOfContents:
17 startLevel: 1
18 highlight:
19 anchorLineNos: false
20 codeFences: true
21 guessSyntax: false
22 hl_Lines: ""
23 lineAnchors: ""
24 lineNoStart: 1
25 lineNos: true
26 lineNumbersInTable: false
27 noClasses: true
28 style: native
29 tabWidth: 4
30
31# Multi-lingual mode config
32# There are different options to translate files
33# See https://gohugo.io/content-management/multilingual/#translation-by-filename
34# And https://gohugo.io/content-management/multilingual/#translation-by-content-directory
35
36#defaultContentLanguage: en
37
38languages:
39 en:
40 languageName: English
41 contentDir: content
42 weight: 1
43 de:
44 languageName: German
45 contentDir: content.de
46 weight: 2
47
48menu:
49 # before: []
50 after:
51 - name: "Contact"
52 url: "mailto:minnemann.g@gmail.com"
53 weight: 10
54 - name: "Github"
55 url: "https://github.com/Abl3t0nnile"
56 weight: 20
57
58params:
59 # (Optional, default light) Sets color theme: light, dark or auto.
60 # Theme 'auto' switches between dark and light modes based on browser/os preferences
61 BookTheme: "auto"
62
63 # (Optional, default true) Controls table of contents visibility on right side of pages.
64 # Start and end levels can be controlled with markup.tableOfContents setting.
65 # You can also specify this parameter per page in front matter.
66 BookToC: true
67
68 # (Optional, default none) Set the path to a logo for the book. If the logo is
69 # /static/logo.png then the path would be logo.png
70 BookLogo: /logo.png
71
72 # (Optional, default none) Set leaf bundle to render as side menu
73 # When not specified file structure and weights will be used
74 # BookMenuBundle: /menu
75
76 # (Optional, default docs) Specify root page to render child pages as menu.
77 # Page is resoled by .GetPage function: https://gohugo.io/functions/getpage/
78 # For backward compatibility you can set '*' to render all sections to menu. Acts same as '/'
79 BookSection: docs
80
81 # Set source repository location.
82 # Used for 'Last Modified' and 'Edit this page' links.
83 BookRepo: https://github.com/Abl3t0nnile/website
84
85 # Configure the date format used on the pages
86 # - In git information
87 # - In blog posts
88 BookDateFormat: "January 2, 2006"
89
90 # (Optional, default true) Enables search function with flexsearch,
91 # Index is built on fly, therefore it might slowdown your website.
92 # Configuration for indexing can be adjusted in i18n folder per language.
93 BookSearch: true
94
95 # (Optional, default true) Enables comments template on pages
96 # By default partals/docs/comments.html includes Disqus template
97 # See https://gohugo.io/content-management/comments/#configure-disqus
98 # Can be overwritten by same param in page frontmatter
99 BookComments: false
100
101 # /!\ This is an experimental feature, might be removed or changed at any time
102 # (Optional, experimental, default false) Enables portable links and link checks in markdown pages.
103 # Portable links meant to work with text editors and let you write markdown without shortcode
104 # Theme will print warning if page referenced in markdown does not exists.
105 BookPortableLinks: true
106
107 # /!\ This is an experimental feature, might be removed or changed at any time
108 # (Optional, experimental, default false) Enables service worker that caches visited pages and resources for offline use.
109 BookServiceWorker: true
110
111 # /!\ This is an experimental feature, might be removed or changed at any time
112 # (Optional, experimental, default false) Enables a drop-down menu for translations only if a translation is present.
113 BookTranslatedOnly: false
Now, that our site is configured, we can now take a first look. To test a page in Hugo, simply type hugo server
into the command line, while in the project directory. Hugo now creates the website and runs it on a local host. The address will be shown in the command line. As long as we keep the server running, hugo will update the site on every change we make to the code.
Although it’s empty our page is now complete. All we have to do, is create some content and push the changes to our production repo.
4 Content management #
Content management and thus creation again depends heavily on the chosen theme. Most Hugo themes are build for one page designs or blogging purpose and don’t need a special file system to organize content. Since Hugo Books is a theme aimed at building documentation pages for software projects, it offers a lot more options for content management. I will cover the specifics to this theme in a different article and limit this article to the common basics.
4.1 Front matter #
Front matter is a tool within Hugo, to associate metadata with a content file, directly from that files header. It is used to store and read important information on the document itself. The title, category, tags or date of publication are good examples for data you want to provide inside a documents front matter. As with most configuration in Hugo, front matter can be written in different formats.
The following examples shows the syntax of front matter headers and are taken from the official Hugo documentation.
YAML Syntax
This a basic example of a front matter written in .yaml.
1---
2categories:
3- Development
4project_url: https://github.com/gohugoio/hugo
5series:
6- Go Web Dev
7slug: hugo
8tags:
9- Development
10- Go
11- fast
12- Blogging
13title: 'Hugo: A fast and flexible static site generator'
14---
TOML Syntax
This is a basic example of front matter syntax written in .toml.
1+++
2categories = ["Development"]
3project_url = "https://github.com/gohugoio/hugo"
4series = ["Go Web Dev"]
5slug = "hugo"
6tags = ["Development", "Go", "fast", "Blogging"]
7title = "Hugo: A fast and flexible static site generator"
8+++
4.2 File structure #
Everything you see on a page setup with hugo, lives in the /content
folder inside the projects root directory. This contains then a collection of content files or sub folders, to further categorize the content.
Most Hugo sites provide blogging capabilities. Each post in the blog lives inside the /posts
folder inside the /content
folder. Another common place to store content is the /docs
folder, which also lives inside /content
. Documents can either be named themselves or stored in a named folder. The latter options needs the files ALL be named index.md
.
4.3 Taxonomies #
By default, Hugo uses so called taxonomies, to manage content. The official documentation says: Taxonomies are classifications of logical relationships between content. In the official examples they are used, to implement a Movie database, with standardized metadata, about actors, director, genre, etc. for each movie.
Basically taxonomies can be seen as categories for your content, and most of the blogging templates will provide a TOC with links to all taxonomies used on the site. The two basic taxonomies, which work out of the box are category
and tag
. If we where to write an article for our blog, we would then give it a category e.g. coding
and provide some tags e.g. python
, web-app
and flask
. The taxonomies of any document are specified in its front matter.
4.4 Adding posts #
…
5 Publication #
To be continued …