How to build a lightning fast static website with Hugo

Hugo is a static site generator (SSG) written in Go (also known as Golang), a high-performance compiled programming language often used to develop applications and backend services.

Today, Hugo is able to render most websites in seconds (<1ms per page). That explains why Hugo bills himself as “the world’s fastest framework for building websites.”

In this article, we’ll take a look at the history of Hugo, what makes it so fast, and how you can start building your own static Hugo site.

Steve France originally developed the Hugo static site generator in 2013, and Bjørn Erik Pedersen took over as the project’s lead developer in 2015. Hugo is an open source project, which means anyone can view and improve his content. code.

As a static site generator, Hugo takes Markdown content files, runs them through theme templates, and spits out HTML files that you can easily deploy online, and it’s all extremely fast.

In 2021, there are dozens, if not hundreds, of static generators. Each static site generator has its appeal. Jekyll is popular with Ruby developers, and while not as fast as other options, it was one of the first static site generators to see widespread adoption. Gatsby is another popular SSG that is well suited to developing statically deployable sites that are dynamic in functionality.

Hugo is fast


In terms of raw performance, Hugo is the best static site generator in the world. Compared to Jekyll, Forestry showed that Hugo was 35 times faster. Similarly, Hugo can render a 10,000-page site in 10 seconds, a task that would take Gatsby more than half an hour to complete. Hugo is not only the fastest SSG in terms of build times, but it’s also quick to install.

Hugo ships as a self-contained executable, unlike Jekyll, Gatsby and other SSGs which require installation of dependencies with a package manager. This means you can download and use Hugo immediately without having to worry about software dependencies.

Making templates is easy in Hugo


In SSG jargon, “templates” refers to the process of adding placeholders for inserting dynamic content within an HTML page. To access the title of a page, you can use the variable {{.Title}}. Therefore, within a Hugo HTML template, it is common to see the {{.Title}} wrapped in H1 tags like so:

<h1>{{ .Title }}</h1>

At build time, Hugo will automatically grab the title within a content file and insert the title between the two tags. Hugo has a variety of built-in template variables, and you can even write custom functions to process data at compile time. For template creation, Hugo uses Go’s built-in libraries, html/template and text/template. This helps reduce app clutter because Hugo doesn’t need to install third-party libraries to create templates. Below is an example of an index.html homepage template from the popular Ananke theme. As you can see, it looks like a standard HTML file with some additional template code.

How to install Hugo


Hugo ships as a compiled executable, which means you won’t have to download and manage many dependencies just to get started. It is available for macOS, Windows and Linux.

How to install Hugo on macOS and Linux


The recommended installation method for macOS and Linux requires Homebrew, a package manager for installing and updating applications. If you don’t already have Homebrew installed, you can install it by running the following command in Terminal:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Once Homebrew has been installed, run the following command to install Hugo:

brew install hugo

How to install Hugo on Windows


For Windows users, Hugo can be installed using the Chocolatey or Scoop package managers. Since the instructions for installing Chocolatey and Scoop are a bit more complex than Homebrew.

After installing Chocolatey or Scoop, you can install Hugo using one of the following commands (depending on your package manager):

choco install hugo-extended -confirm
scoop install hugo-extended

Hugo commands and settings


Before we dive into creating a static site with Hugo, let’s familiarize ourselves with the various CLI commands and configuration file parameters.

Hugo CLI Commands

  • hugo check – run various verification checks
  • hugo config – show the configuration of a Hugo site
  • hugo convert – convert content to different formats
  • hugo deploy – deploys your site to a cloud provider
  • hugo env – displays Hugo version and environment information
  • hugo gen – provides access to various generators
  • hugo help – displays information about a command
  • hugo import – allows you to import a site from another location
  • hugo list – displays a list of various types of content
  • hugo mod – Provides access to various module helpers
  • hugo new – Allows you to create new content for your site
  • hugo server – Starts a new content server local development
  • hugo version: show the current version of Hugo

Hugo CLI also has a variety of flags to specify additional options for some commands. To see a complete list of Hugo’s flags (there are many), we recommend using the hugo helper command to display a list of all available flags.

How to create a Hugo site


Now that we’ve covered how to install and use the Hugo CLI and the basics of the Hugo configuration file, let’s create a new Hugo site.

To create a Hugo site, use the following command (if you wish, you can change my-hugo-site to something else):

hugo new site my-hugo-site

Hugo content folder


The content folder is where the actual content of the publication goes. Hugo supports both Markdown and HTML formats, with Markdown being the most popular option due to its ease of use. In addition to being the general storage space for posts, you can use the content folder to further organize post content.

Hugo treats each top-level directory in the content folder as a content section. Content sections in Hugo are similar to custom post types in WordPress. For example, if your site has posts, pages, and podcasts, your content folder will have post, page, and podcast directories where the content files for these different types of posts will be located.

Hugo Designs Portfolio


The layouts folder contains HTML files that define the structure of your site. In some cases, you may see a Hugo site without a layouts folder because it doesn’t have to be in the root directory of the project and can reside inside a themes folder.

Similar to WordPress themes that use PHP to create templates, Hugo templates consist of base HTML with additional dynamic templates powered by Golang’s built-in template and text/template libraries. The various HTML template files needed to generate the HTML markup for your site are located in the layouts folder.

Hugo Theme Folder


For sites that prefer a more self-contained way of storing template and asset files, Hugo supports a theme folder. Hugo themes are similar to WordPress themes in that they are stored in a theme directory and contain all the templates necessary for a theme to work.

While some Hugo users prefer to keep theme-related files in the project root directory, storing these files within the theme folder allows for easier management and sharing.

Hugo’s data folder


Hugo’s data folder is where you can store supporting data (in JSON, YAML, or TOML format) that is needed to generate your site’s pages. Data files are beneficial for larger data sets that can be cumbersome to store directly in a template or content file.

For example, if you wanted to create a list of inflation rates in US dollars from 1960 to 2020, about 80 lines would be needed to represent the data (one line for each year). Instead of putting this data directly into a content file or template, you can create it in the data folder and populate it with the necessary information.

Hugo Static Folder


Hugo’s static folder is where you store static assets that don’t require any additional processing. The static folder is usually where Hugo users store images, fonts, DNS verification files, and more. When a Hugo site is built and saved to a folder for ease of deployment, all files in the static folder are copied as-is.

If you’re wondering why we didn’t mention JavaScript or CSS files, it’s because they’re often dynamically rendered through pipelines during site development. In Hugo, JavaScript and CSS files are commonly stored inside the theme folder because they require additional processing.

How to add a theme to a Hugo site


Downloading and installing a pre-built theme is a great way to get started with Hugo. Hugo themes come in all shapes and sizes, and many of them are available for free on the official Hugo theme repository. Let’s go ahead and install the popular Hyde theme on our Hugo site.

First, navigate to your project’s theme folder in Terminal:

cd <hugo-project-directory>/themes/

Next, use Git to clone the Hyde theme to your project’s theme directory.

git clone https://github.com/spf13/hyde.git

Next, add the following line to your config.toml file to activate the Hyde theme:

theme = "hyde"

At this point, the Hyde theme is installed and configured. The next step is to start Hugo’s embedded development web server to view the site in your web browser.

How to add content to a Hugo site


Adding content to a Hugo site is very different from a full CMS like WordPress or Ghost. With Hugo, there is no built-in CMS layer to manage your content. Instead, you are expected to manage and organize things as you see fit.

In other words, there is no explicitly “correct” way to manage content in Hugo. We’ll share a method for adding and managing content in this section, but feel free to change things as you get more familiar with Hugo.

Content sections in Hugo


In Hugo, the first content organization tool you have at your disposal is the content section. A content section in Hugo is similar to a post type in WordPress: not only can you use it as a content filter, but you can also use it as an identifier when creating custom themes.

For example, if you have a blog content section folder, you can use it to store all of your blog posts and render a specific page template that only applies to blog posts.

How to add posts in Hugo


With that in mind, let’s create a blog post content section and add a few pieces of content. Create a new folder called posts in your project’s content folder; this is the content section.

Let’s create another organizational layer inside the posts folder by creating a 2021 folder. At this point, your content directory should look like this:

Now, let’s create our first post. As we discussed earlier, Hugo supports Markdown and HTML files for content. In general, it’s best to stick to Markdown files because they’re easier to write, format, and read.

In the content/posts/2021 folder, create a new file ending in .md (the Markdown file extension). You can name the file anything you like, but the recommended syntax for naming a Hugo content file is YYYY-MM-DD-a-sample-post.md.

In addition to manually creating a content file, you can also use the Hugo CLI to create a new post with the following command (make sure you run the command from your project directory):

hugo new posts/2021/2021-08-30-a-sample-post.md

Notice how the content folder is missing from the path above. This is because Hugo assumes that all content files will go into the content folder by default.

If you open the newly created content file, you should see some lines of metadata at the top of the document that look something like this:

---

title: "2021 08 30 a Sample Post"

date: 2021-08-30T13:44:28+09:00

draft: true

---

This metadata, which is formatted in YAML, is called “feedstock”. The automatically generated preliminary information is a significant benefit of using the Hugo CLI. The parent topic is where a post’s unique data (post name, data, draft status, tags, categories, etc.) is stored. The default format for preliminary matter can be set per section using archetypes.

Now let’s add some text to the post. When writing a post, always make sure your content is below the cover like this:

Once you save the content file, you should see Hugo rebuild your site in Terminal. In the screenshot below, you can see that Hugo rebuilt the entire site in 22ms.

If you visit your Hugo site in your web browser, you should see the new post.

How to add a page in Hugo


Now that we’ve added a post to our Hugo site, let’s add a page. Most content management systems, including WordPress, distinguish between posts and pages. Typically, a post is a dated snippet of content, while a page consists of permanent or static content.

To create a page, we first need a page content section. To do this, create a folder called Pages in Hugo’s content folder. Then use the command below to add a new “About” page to your site:

hugo new pages/about.md

Notice how the naming convention for pages differs from posts. Unlike posts, pages aren’t tied to a specific date, so there’s no need to include the creation date in the file name.

Now, let’s add some text to the “About” page:

At this point, you should see the About page in your web browser:

Now that we have two content sections, posts and pages, let’s see how to do some customizations on the site, like editing the title and description, adding the About page to the sidebar menu, changing the format of the links permanent and remove pages from the post feed.

How to change the site title and description


The exact method to change the site title and description depends on the site settings and/or the active theme. For the Hyde theme, the site title and description can be changed in the Hugo configuration file (config.toml).

We know this from the following theme code that displays the sidebar:

<aside class="sidebar">

<div class="container sidebar-sticky">

<div class="sidebar-about">

<a href="{{ .Site.BaseURL }}"><h1>{{ .Site.Title }}</h1></a>

<p class="lead">

{{ with .Site.Params.description }} {{.}} {{ else }}An elegant open source and mobile first theme for <a href="http://hugo.spf13.com">hugo</a> made by <a href="http://twitter.com/mdo">@mdo</a>. Originally made for Jekyll.{{end}}

</p>

</div>

<nav>

<ul class="sidebar-nav">

<li><a href="{{ .Site.BaseURL }}">Home</a> </li>

{{ range .Site.Menus.main -}}

<li><a href="{{.URL}}"> {{ .Name }} </a></li>

{{- end }}

</ul>

</nav>

<p>{{ with .Site.Params.copyright }}{{.}}{{ else }}© {{ now.Format "2006"}}. All rights reserved. {{end}}</p>

</div>

</aside>

How to use shortcodes in Hugo


Hugo shortcodes are similar to partials in that they allow code reuse across a variety of pages. Shortcodes are HTML files that reside in the /layouts/shortcodes folder. The main difference is that partials apply to HTML templates, while shortcodes apply to Markdown content pages.

In Hugo, shortcodes allow you to build modules of functionality that you can use on the pages of your site without managing code changes for each page.

If you have a blog, you may need to review the body content of your posts to update the year references to the current year. Depending on how many posts you have on your site, this task can take a long time!

By using a Hugo shortcode in your content files, you won’t have to worry about updating year references ever again!

Let’s start by creating a shortcode in /layouts/shortcodes/current_year.html with the following content:

{{ now.Format "2006" }}

How to add images to a Hugo post


Unlike WordPress and other full content management systems, Hugo does not include a drag and drop system for managing images. Therefore, the design of an image management system is offloaded to the end user.

While Hugo doesn’t have a standardized way of managing images, a popular method is to store images in the /static folder and reference them in posts and pages using a shortcode. Let’s see how a basic organization of images can be done in Hugo.

The first thing we’ll need to do is create an organizational structure for our image library. While this sounds complex, all that is required is the creation of a few additional directories within the /static folder.

Let’s start by creating an uploads folder in /static. Inside the uploads folder, create a folder called 2021 to contain all images uploaded in 2021.

Next, let’s add two images (blue1.jpg and blue2.jpg) to the 2021 folder.

In HTML, images are displayed with the tag. For example, to display blue1.jpg, we can use the following HTML:

<img src="/uploads/2021/blue1.jpg" alt="Blue is the warmest color!">

While it’s possible to add this HTML directly to your Markdown content file, it’s best to create a shortcode that you can use to display any image in your uploads folder. This way, if you ever need to update the img tag, you can edit the shortcode template without editing every instance of the img tag.

To create the shortcode template, create a new file at /layouts/shortcodes/img.html with the following content:

<img src="/uploads/{{ .Get "src" }}" alt="{{ .Get "alt" }}

Next, add the shortcode below to a blog post:

{{< img src="2021/blue1.jpg" alt="Blue is also the coolest color!">}

How to implement a Hugo site


Until this post, you’ve learned how to install Hugo, create a site, add a theme, make basic edits to configuration files, and expand your site’s functionality with partials and shortcodes. At this point, you should have a functional site that is ready to go online.

Since Hugo is a static site generator, you can deploy the HTML, CSS, and JS it generates anywhere with a web server. Since the technical requirements for serving static sites are so low, you can host them for free on a wide range of providers like Netlify, Vercel, Cloudflare Pages, and more.

Previously, we used the hugo -D server to launch a local development server to preview changes to our site in real time. To generate the entire site, we can use the hugo command in the root directory of our project. After the site build is complete, you should see a new public folder in your project directory. Inside this folder, you will find all the files that need to be uploaded to a server or cloud storage service like Amazon S3.

Building your site locally and manually uploading it to Amazon S3 or to a server running Nginx is one way to implement a statically generated site. However, it’s not the most efficient because it requires you to manually upload new files every time you make a change.

Instead, a better option is to link the Hugo project folder to a GitHub repository, and link the GitHub repository to an automated deployment service like Netlify. With this setup, you can edit your site, push changes to GitHub, and trigger a new build and deployment to Netlify without any manual intervention. Now, let’s see how to do all this.

How to upload your Hugo project to GitHub


First, you will need to create a GitHub repository for your project. To do this, create a GitHub account (if you don’t already have one) and download the official GitHub desktop app. After installing the GitHub app, click File on the menu bar and select New repository. Give the repository a name of your choice, leave the other options to their default states for now, and click Create repository.

By default (on macOS), the GitHub app creates new repositories in /Users/username/Documents/GitHub. Since we call our repository my-hugo-site, our repository can be found at /Users/brianli/Documents/GitHub/my-hugo-site.

Next, move all files from the original project folder to the new GitHub repository folder. Be sure to delete the public folder because you don’t need to upload that folder to GitHub.

If you go back to the GitHub app, you should now see a list of changed files. To upload the repository to GitHub, add a summary, click Commit to Main, and click Publish Repository in the upper right corner.

By default, the “Keep this code private” option is checked. If you want your code to be open source and publicly accessible, feel free to uncheck it. Finally, click Publish Repository again.

Now if you go to GitHub, you should see your online repository like this:

How to link the GitHub repository to Netlify


If you don’t have a Netlify account yet, sign up here. To link a GitHub repository to Netlify, click New site from Git in the Netlify dashboard.

Under Continuous Deployment, select the GitHub option.

Next, use the search box to find the repository for your Hugo project.

Next, specify the settings for continuous deployment. Since Netlify can detect a Hugo configuration, the default configuration should work fine for a basic deployment.

As you become more familiar with Hugo, you’ll be able to delve into environment variables, custom build commands, and more. For now, setting the build command in hugo and the public directory to public will allow you to deploy a simple Hugo site. After specifying the build command and public directory, click Deploy Site.

Since Hugo is such a fast static site generator, deployment should only take a few seconds for a basic site. Once the deployment is complete, you will be able to see a test URL in the Netlify Dashboard. Click the URL to see the deployed site.

At this point, you can set up a custom domain and SSL certificate for your Netlify-hosted site. To do so, we recommend consulting the official Netlify documentation.

Since we’ve linked Netlify to GitHub, a new commit to the Hugo project’s GitHub repository will automatically trigger a new deployment on Netlify.

This is how it is possible to build a lightning fast static website with Hugo..

Summary


Hugo is one of the most popular static site generators in the world, and for good reason. Not only does it have super fast build processing, but it also ships with powerful templating capabilities that support partials and shortcodes.

In this tutorial, you learned how to set up Hugo, create a new project, add content files, edit theme files, and deploy a finished static site. We recommend checking out the official Hugo documentation for more information on Hugo and its more advanced features, such as custom functions, front-end stuff, and CSS/JS buildpacks.

What do you think of Hugo and other static site generators? Please let us know in the comments below!

Save time, costs and maximize site performance with:

  • Instant help from WordPress hosting experts, 24/7.
  • Cloudflare Enterprise integration.
  • Global audience reach with 28 data centers worldwide.
  • Optimize with our built-in application performance monitoring.
  • All that and much more, in a plan with no long-term contracts, assisted migrations and a 30-day money-back guarantee.

Table of Contents

Stay in the Loop!

Subscribe to Phluit’s Newsletter and stay updated with the latest.

Subscription Form

Ready to buy or sell your
online business?

Explore listings or list your business today on Phluit. Start your journey now to achieve your business goals with our trusted platform.

Share to...