A Comprehensive Guide on Building Your First Site with Hugo
Table of Contents
Introduction⌗
Hugo is a great framework to build your blog with.
Unfortunately, Hugo doesn’t ship a WYSIWYG editor like WordPress which makes it difficult for a person without coding experience to understand what’s going on with the framework. It becomes a bit tedious to grasp the whole picture of Hugo and its terminologies if you haven’t worked with a static site generator before.
I learnt Hugo with just the documentation and the Discourse. But docs are never fun, are they? Not everyone needs to spend so much of time reading them just for a personal blog.
So, this is a beginner-friendly comprehensive guide on creating your own blog/site. At the end of this guide, you will have your own functional, minimalist blog up and running for free. Along the way, I explain Hugo terminologies in a simpler fashion, comparing them to WordPress (my previous platform of choice) as needed.
Please Note⌗
- Appropriate resources have been linked wherever possible.
- Feel free to skip a step or two if you are already familiar with them.
- Use the Table of Contents to navigate through the guide as needed.
- I have chosen to use Anatole theme in this guide since it’s fairly minimal. Updates to Hugo or the theme itself shouldn’t drastically make this post outdated.
- Your result might not be exactly same as mine if you are starting with raw Anatole, because I have used some extra (not documented in Anatole’s docs) configuration.
- I have made use of comments, in places, to explain the code. You can entirely omit them in your configs.
- Most of the commands mentioned here assume you are in your site’s root directory.
Prerequisites⌗
- Knowing basic use of Terminal/Powershell; like opening a particular path/location.
- Install Git
- A GitHub Account (Free)
- Install Scoop if using a Windows machine
- Install Homebrew if using a Linux/Mac machine
- A code editor. I use Visual Studio Code.
The setup process might take a long time according to your level of experience. And don’t freak out if you are seeing all this first time. You don’t need to be an expert at all these things. Just copy-pasting would do as well.
If you still don’t want to fiddle with your machine, you can try out something like Forestry or Stackbit. I haven’t used them since that would mean giving up the fine-grain control and other benefits of Hugo ;)
Sample Code to Clone/Compare⌗
Here’s a public GitHub repo which you can clone or compare your progress with. If you don’t know what a repo is…just think of it as publicly available folder for now.
Going through the sample files and the folder structure might make the picture clearer.
And here’s the published version of the site we would build today.
Installing Hugo⌗
Let’s begin with installing Hugo on your machine. Yep. Hugo is installed locally on your machine and not on a server. Here’s Hugo’s official Installation Guide.
The installation process differs OS to OS, but I would recommend sticking with a package manager i.e. Scoop or Homebrew to minimize chances of error. Also, make sure that you get the extended version of Hugo with the capability of SASS/SCSS processing.
To install on a Windows machine, you just need to run:
|
|
On Linux/Mac, run this:
|
|
Creating the Site Directory⌗
Great! You moved past the installations. Steps, here onward, are quite easy now.
Let’s move on and create our Hugo Site’s directory, shall we?
To create one, fire up your terminal at the preferred location and enter:
|
|
Breaking down the command:
hugo new site
just creates the basic directory structure of a Hugo site<your site's name>
should be replaced with anything; a folder is created with this name-f yml
specifies the preferred syntax for the site’s configuration file. I recommend sticking with YAML since it is more readable.
Now, you have your site’s root directory set up. Open it and you will find the following directory structure there. Ignore any unfamiliar terms for now.
|
|
Here’s the official documentation to read further: Directory Structure - Hugo.
Installing Theme⌗
I recommend installing the theme as a git submodule since it simplifies the update and deployment process.
Initializing Git⌗
Git is a version control system used by coders to maintain their code bases. It’s like creating small restore points each time you make a change in the code so that you have a fallback plan in case you mess up.
Assuming you installed Git as per the instructions in the prerequisites section, open the terminal back at the site’s root directory and run git init
. This tells git to start tracking changes there.
Also add a .gitignore
file to keep Git from uploading the custom generated resources to GitHub in later stage. The file should simply contain just this:
|
|
Adding the theme as a Git Submodule⌗
After initializing git, we can proceed to install themes. Open your preferred theme’s documentation and search for installation instructions. Copy/Paste the command given for git submodule integration.
For example, we will be using the Anatole theme in this tutorial. So, to install it you would run:
|
|
Configuring Our Site⌗
As I mentioned earlier, config.yml
is your site’s admin panel. All the major settings are controlled with this file. Let’s set up ours now. Copy and paste the following code in your config.yml
file (replacing the existing one).
|
|
Creating A Post⌗
In Hugo, all your posts/pages reside in the content
folder of your site’s directory. And are bundled relative to the root of your site. For example, if you have an about page on your site at examplesite.com/about
you will have an about.md
file in the content directory. Or if you have examplesite.com/blog/post
, you will have post.md
inside blog
folder in the content
directory.
Make no mistake though, your file structure and the permalink/URL are not strictly connected. You can override it in the front-matter of the post.
What is a URL?⌗
|
|
Breaking Down:
- baseURL is defined in the
config
file section
is by default defined by the directory structure inside the content folder (can be over-ridden in theconfig
file)slug
is defined in the Front-Matter (is the filename by default)
What is ‘Front-matter’?⌗
Each post in Hugo consists of front-matter. Think of it as settings of each individual post typed out at the beginning of each file. Like Gutenberg’s side panel. So, things like title, featured image, author, categories and tags would be set using the front-matter in Hugo.
In case you come across another site’s code, please keep in mind that front-matter can also be defined in TOML/JSON. See the official documentation here.
What is the deal with the .md extension?⌗
One of the many perks of using Hugo is to be able to write posts using the efficient Markdown syntax. It is like a simple list of rules to speed up your writing process without touching any HTML. See the Markdown Guide here. And believe me, once you get to know it, there’s no going back. I learnt about it last year, and it has been quite life changing.
How to organize posts in Hugo?⌗
You can organize your posts into separate folders and drill down as much as you need. But as we are setting up a blog, we will need just one folder to organize our posts in. Your directory structure inside the content folder would look something like this where any page outside the blog folder would be a separate page (e.g. Contact Page or About Page; similar to WordPress Pages):
|
|
Where do the image files go?⌗
Images, in Hugo, can be placed in two different ways. Either they can be part of a Page Bundle or be placed in a central location under the static
directory like wp-media
in WordPress.
Which is better? Creating page bundles unlocks the power of Hugo’s unique Image Processing Methods. Besides that, it would be just a matter of personal preference.
Currently, you don’t need to worry about the Page Bundles part. We will be keeping things simple and placing images under static directory as Anatole doesn’t use Image Processing
. Your static folder should look like this:
|
|
Creating first archetype⌗
Archetypes are like predefined settings (front-matter) for your new posts. Why create this separately? There are many variables one can define in the Front-matter. Some variables also vary with the theme. Hence to save us from the trouble of manually going through a lengthy list of variables each time, we define archetypes. Defining archetype also helps you auto-populate dynamic fields such as Date
right at the time of creating the post with just one single line. Read more about it here.
If you check your archetypes
directory, you’ll find a default.md
there. That’s just the basic skeleton. Let’s define our own archetype now. Create a file called post.md
in the same place and copy the following content into it:
|
|
Actually creating the first post⌗
Type in the following into the terminal.
|
|
Breaking down the command:
--kind
tells hugo which archetype to useblog/post1.md
is the relative path to the actual file we need (hugo new
by default creates the file in thecontent
directory)
Open up the file now, set the front-matter whatever you want and type in anything below the closing ---
three dashes. This will be your first post.
How do I setup redirects?⌗
Hugo has in-built support for aliases in the front-matter.
Let’s say someday, back in time, you wrote an article on over-eating. You are now updating it totally…and want to redirect users to the new page.
By defining aliases
variable in the front-matter (of the new post), users that land on the old-post URL will be redirected to the new one. Example:
|
|
Adding an image in between the post⌗
Again, there are two ways to add images in between the post content. You can always go with the markdown style of adding images or use Hugo’s preferred figure
short code.
Here’s an example with all the parameters I think you would ever need:
|
|
To align an image, you can also define the class parameter with all the above as big
, left
or right
(specific to Anatole theme). The following code will align the image to the right and wrap the text around it. Read more about it here.
|
|
What are Hugo Shortcodes?⌗
Similar to WordPress short codes, they allow you to embed various things into your post without actually writing any HTML for them. For example, if you want to embed a YouTube Video in your post, instead of adding the raw iFrame code in the markdown file, you can just write down the following short code, provide the video ID and Hugo will take care of the rest of it:
|
|
Here’s the list of built-in short codes shipped with Hugo. Defining your own short-codes is easy too. A short code is, basically, a repetitive piece of HTML. Receiving parameters and processing them requires the use of Go templating, though.
Serving Site Locally⌗
Phew! Now that we have configured our site successfully and made our first post, it’s time to see what our site looks like. Let’s do this. Open your terminal at hugo site’s root directory and simply run:
|
|
Now follow the link shown in the terminal or just navigate manually at localhost:1313 and you will see your site served locally. The local server monitors the site for changes and automatically reloads the site with each change you make.
Deploying the Site⌗
All that’s left now is deploying our site.
Understand How Deployment Works⌗
Hugo is a static site generator. It builds your site into just one folder that includes everything else. If you are hosting the site on your own using Shared Hosting all you need is that one build
folder. But GitHub Pages and Netlify require some additional configuration.
What is ‘GitHub Pages’?⌗
GitHub Pages is a free service to host free static websites right from your git repo. There’s no catch here…except a few limitations.
But, since we are aiming at a free and friction-less hosting, I will be demonstrating GitHub Pages (easy way) configuration here.
Now, GitHub Pages is by default configured to build and host Jekyll websites. So, to avoid GitHub treating our site as one, create a blank file named .nojekyll
inside the site’s root directory.
And add the following line in your config.yml
file:
|
|
Building your Site⌗
Now to get that final folder of your site, enter this in your terminal (at the site’s root directory):
|
|
Breaking down the command:
- Simply running
hugo
alone builds your site --gc
flag deleted the unused cache files after the build--minify
obviously, minifies the files
First Commit and Pushing to GitHub⌗
A commit is like saving a snapshot in Git. You can return your entire codebase to the exact state of your commit any time later down the course.
So now that we have everything ready to be deployed, let’s create our first commit and move the codebase to GitHub. Think of GitHub as cloud-storage for your code. Only except moving files using a browser, you use your terminal.
First create a repository inside your GitHub Account. Do not initialize it with anything. Set it to Public and click next. GitHub will now give you an SSH address. Copy it.
Go to your terminal and execute the following commands one-by-one:
|
|
Enabling GitHub Pages⌗
- Head on to the Settings section of your GitHub repo in the browser and scroll down to the GitHub Pages Section.
- Under source, select the main branch and the docs folder. Click Save.
- Don’t forget to update the
baseURL
in theconfig.yml
file. Otherwise, the site won’t load. - That’s it!
Congratulations! You just published your own site!
If you are happy with the results produced and are serious about your blog/website grab a custom domain name and head on to hosting with Netlify (also free).
How to update the published site’s content?⌗
You can always make whatever you need locally and then push them to GitHub once you are satisfied. Or even make use of Git Branches.
Example Workflow:
|
|
Other Questions⌗
What other features does Anatole support?⌗
- Anatole supports both Disqus and Commento for comments.
- It has built-in support for FormSpree Contact Forms.
- You can add custom CSS and JS using the
config
file (instead of over-riding the default ones). - Anatole ships with both KaTex and MathJax for equation rendering.
- Syntax highlighting is supported with Chroma.
Where do you get the icon codes for the homepage?⌗
The icons are loaded from the Font Awesome library, and you can find them on Font Awesome’s Site.
How do you generate your site’s favicons?⌗
this tool should help you with it.
How to over-ride theme’s styles and templates?⌗
With Hugo, you are in charge of your site’s code. To over-ride a theme’s CSS or layout is as simple as replicating the directory structure inside your theme at the root of your site’s directory and editing the files. See Hugo’s look-up order.
Example:
Say your theme controls the home page’s style using home.css
file placed inside the assets/css/
directory, then all you have to do is recreate the same path at the root of your site and place the edited file in there. Like this:
|
|
Is there a way to get live in seconds?⌗
Run the following in your terminal. Edit the values of the files as necessary and push back the code to your own GitHub public repository and you can save yourselves some time.
|
|