A terminal window on a laptop computer.
Fatmawati Achmad Zaenuri/Shutterstock

Static websites are easy to create and blazingly fast to use. If you learn to use Hugo, you can generate theme-based static websites on Linux. Creating websites is fun again!

The Hugo Website Generator

A static site is one that doesn’t create or modify web pages on the fly. There’s no background database, e-commerce processing, or PHP. All the web pages are entirely pre-built and can be served up to visitors very quickly.

But that doesn’t mean a static site has to be boring. They can use everything HTML provides, plus cascading style sheets (CSS), and JavaScript. They can also easily have things like image carousels and web pages sliding over background images.

The Hugo site generator works with a template and any content you’ve created to generate a completed website. You can then place it on a hosting platform and immediately have a live website.

Hugo uses markdown for the pages and blog entries you create. Markdown is just about the simplest markup language there is, which makes maintaining your site simple.

Hugo’s configuration files are in Tom’s Obvious, Minimal Language (TOML) and YAML Ain’t Markup Language (YAML), which are just as easy. Another bonus is Hugo is blazingly fast—some sites load in less than a second. It has many templates you can choose from, and more are being added all the time, so it’s easy to get started. Just pick a template and add some content that makes it yours.

Hugo also acts as a tiny web server right on your computer. You can see a live version of your website while you design and create it, and whenever you add a new post. It also auto-updates each time you “Save” in the editor, so you can immediately see the effect of your changes in your browser.

Hosting Your Site

When it comes to hosting your static website, you’re spoiled for choice. Most companies offer free hosting for personal or open-source use. Of course, you can also choose a regular web-hosting company, like any of the following:

  • Aerobatic
  • Amazon S3
  • Azure
  • CloudFront
  • DreamHost
  • Firebase
  • GitHub Pages
  • GoDaddy
  • Google Cloud Storage
  • Heroku
  • GitLab Pages
  • Netlify
  • Rackspace
  • Surge

RELATED: How to Host a Static Website for Free on Google's Firebase Hosting Platform

Installing Hugo

Along with Hugo, you need to have Git installed. Git was already installed on Fedora 32 and Manjaro 20.0.1. On Ubuntu 20.04 (Focal Fossa,) it was added automatically as a dependent of Hugo.

To install Hugo on Ubuntu, use this command:

sudo apt-get install hugo

On Fedora, you need to type:

sudo dnf install hugo

The command for Manjaro is:

sudo pacman -Syu hugo

Creating a Website with Hugo

When we ask Hugo to make a new site, it creates a set of directories for us. These will hold the different elements of our website. This isn’t the final website that will be uploaded to your hosting platform, however. These directories will hold the theme, configuration files, contents, and images Hugo will use as input when we ask it to build the actual website.

It’s like the difference between source code and a compiled program. The source code is the stuff the compiler uses to generate the final product. Similarly, Hugo takes the contents of these directories and generates a working website.

The command we’re going to run will create a directory with the same name as the site you want to create. That directory will be created in the directory in which you run the command.

So, move to the directory in which you want your website to be created. We’re using our home directory, so we type the following:

hugo new site geek-demo

This creates a “geek-demo” directory. We type the following to switch into that directory and run ls:

cd geek-demo/

We see the “config.toml” configuration file and the directories that have been created. These are virtually empty, though, as this is just the scaffolding for the website.

Initializing Git and Adding a Theme

We need to add a theme so Hugo knows what we want the finished site to look like. To do this, we have to initialize Git. In the root folder of your site (the one that contains the “config.toml” file), run this command:

git init

There are hundreds of themes you can choose from, and each one has a web page that describes it. You can run a demo of a theme and find out what the command is to download it. We’ll use one called Meghna.

To incorporate that theme into our website, we need to switch to our “Themes” folder and run the git clone command:

cd themes
git clone https://github.com/themefisher/meghna-hugo.git

Git displays some messages as it progresses. When it’s finished, we use ls to see the directory containing the theme:


Hugo themes include a working example website. You must copy that default site into the directories of your website.

First, return to the root directory of your website. We’re using the -r (recursive) cp option to include subdirectories, and the -f (force) option to overwrite any existing files:

cd ..
cp themes/meghna-hugo/exampleSite/* -rf .

Launching Your Site Locally

We’ve done enough to launch a new website locally. It’ll still contain the placeholder text and images, but those are merely cosmetic changes. Let’s verify the technical bits work first.

We tell Hugo to run its web server and use the -D (draft) option to make sure any files that might be tagged with “draft” are included in the website:

hugo server -D

The image below shows the output from our hugo command.

We’re told that Hugo built the site in 142 milliseconds (we did say it was fast, right?). It also tells us to press Ctrl+C to stop the server, but leave it running for now.

Open your browser and head to localhost:1313 to see your website.

A default "Meghna" theme static website in Firefox running on localhost:1313.

Modifying the Default Site Content

While it’s running like this, Hugo is serving the web pages from memory. It hasn’t created the website on the hard drive, but rather, a working copy in RAM. It’s monitoring the files and images on the hard drive, though. If any of them are changed, it refreshes the site in your browser—you don’t even have to hit Ctrl+F5.

Open another terminal window and navigate to the root directory of your website. Open the “config.toml” file in an editor. Change the “baseURL” to the domain on which your website will be hosted and change the “title” to the name of your website. Save your changes, but leave the editor open.

config.toml file in an editor, with changes.

Hugo detects that there have been changes to the “config.toml” file, so it reads those, rebuilds the site, and refreshes the browser.

Refreshed browser with a new web name showing in the tab.

You should now see the name you chose for your site in the browser tab. Getting immediate visual feedback on saved changes significantly speeds up the process of customizing a website.

All themes are different, but we found those we used to be quite simple to follow. The different sections of the website have obvious names, as do the settings in each section, so it’s always obvious what you’re changing.

And, again, as soon as you save a change, you see what you’ve altered in your browser. If you don’t like it, just reverse the change and resave.

The various configuration files that control the website are each dedicated to a single job and labeled in a meaningful way. Tracking them down isn’t difficult, as there aren’t too many places they can be in the directory. Typically, they’re in the “Data” folder.

Because we’re using a bilingual template, our English configuration files are in the “En” subdirectory.

If you open the Data > En > banner.yml file in an editor, you’ll see the collection of settings that govern the banner area of the website.

data/en/banner.yml file in a editor.

When you change the “Title” and “Content” settings, you alter the text on the banner page.

We also changed the “Label” setting, so the button text says “Find Out More.” For your site, you’ll probably want to change the image, too.

banner.yaml file with changes in an editor.

As soon as you save your changes, you’ll see them in your browser.

Default theme static website in Firefox running on localhost:1313.

Changing Other Elements of a Website

You can change all of the other elements in a similar way. Just track down the appropriate configuration file and change the settings and text to suit your needs.

You’ll also want to change the images. The default image will be referenced in the configuration file. You can easily find and take a look at the original image to see what its dimensions are.

Images are placed in the “Static > Images” directory with subdirectories for the different sections of the website. Place any favicons and logos directly in the “Static > Images” directory.

Adding New Blog Content

So far, we’ve looked at changing what’s already there. But, how do we add a new blog post? Hugo uses a concept called “Archetypes” for creating new content. If we don’t create an archetype for our blog entries, a default file will be created for us each time we ask Hugo to create a new blog entry.

This is fine, but with an archetype, we can save ourselves some effort and make sure as much of the front matter as possible is entered for us in advance.

In this theme, blog entries are located in Content > English > Blog. If we open an existing blog entry in an editor—like “simple-blog-post-1.md”—we can see the front matter.

We need to copy that section, edit the current entries so it can be used as an archetype template, and then save it in the “Archetypes” folder. If we name it “blog.md,” it’ll automatically be used as the template for new blog entries.

In gedit, we can do this as follows:

gedit content/english/blog/simple-blog-post-1.md

Highlight the top section including the two dashed lines, and then press Ctrl+C to copy it. Press Ctrl+N to start a new file, and then Ctrl+V to paste what you copied.

front matter in an existing blog entry in an editor.

Now, make the following changes, and be sure to leave a space after the colon (:) in each line:

  • Title: Change this to "{{ replace .Name "-" " " | title }}" (include the quotation marks). A title for each new blog post will be inserted automatically. It’s formed from the file name you pass to the hugo new command, as we’ll see.
  • Date: Change this to {{ .Date }}. The date and time when the blog is created will be automatically entered.
  • Image_webp: This is the path to the blog’s header image in webp format. If the theme can’t find one, it’ll use the image from the next line.
  • image: This is the path to the blog’s header image in JPEG format. You might as well leave these pointing to the default images. Then, all blog posts will have a stopgap image, even before you find, resize, or save a custom one. Once you’ve done that, you can easily edit the file name to match that of your custom image.
  • Author: Change this to your name.
  • Description: You type a short description of each post here. If you change this to an empty string (""), you can type a description for each new blog without having to edit old text.

Edited front matter in an archetype file in an editor.

Save this new file as “archetypes/blog.md,” and then close gedit. Hugo will now use this new archetype whenever you want to create a new blog entry.

Note that our file should have a “.md” extension because we’ll be using markdown to write our blog entry:

hugo new blog/first-new-blog-post-on-this-site.md

Now, we want to open our new blog entry in an editor:

gedit content/english/blog/first-new-blog-post-on-this-site.md

Our new blog post opens in gedit.

New blog post in gedit.

All of the following pieces of the front matter have been added for us:

  • Title: This was deduced from the file name. If it needs any tweaking, you can edit it here.
  • Time and date: These are added automatically.
  • Default image: You’ll probably want to find a relevant, royalty-free image. Drop it in Static > Images > Blog. You’ll have to type the actual file name of the image here.
  • Author: Your name is added automatically.
  • Description: This has been edited.

Write the blog using markdown and use the standard markup for headings, bold, italics, images, links, and so on. Each time you save your file, Hugo rebuilds the website and updates it in your browser.

The image below shows how our new blog entry appears on the home page.

A new blog entry on the home page.

The image below shows how the new blog entry looks on its own page.

A new blog entry on the home page.

After you finish writing your blog post, save the changes, and then close the editor. You can also close your browser because we’re going to stop the Hugo server.

In the terminal window in which the Hugo server is running, press Ctrl+C.

Building the Website

In the root directory of your website, issue the following command to build your website:


Hugo builds the website and lists the number of pages and other components it created. It took 134 milliseconds to create ours.

Hugo creates a new directory called “Public” in the root directory of your website. In the “Public” directory, you’ll find all the files you need to transfer to your hosting platform.

Note that you have to upload the files and directories inside the “Public” directory to your hosting platform, not the “Public” directory itself.

The website files that need to be uploaded to the hosting platform.

Now You Know the Basics

Each theme will require a bit of exploration to figure out how you can get it to look the way you want, but that’s the fun part! Given Hugo’s ability to render changes immediately in a browser window, nothing takes too long.

You’ll probably find that writing your text and finding and trimming images are the parts of the process that take the longest.

The Hugo documentation site is also helpful, but extensive. Hopefully, this basic walk-through will be enough to get you started.

If you use Git and Github, GitLab, or BitBucket, there are also integrations available for those platforms. They watch your remote Hugo repository and rebuild your live site whenever you push changes to it.

Profile Photo for Dave McKay Dave McKay
Dave McKay first used computers when punched paper tape was in vogue, and he has been programming ever since. After over 30 years in the IT industry, he is now a full-time technology journalist. During his career, he has worked as a freelance programmer, manager of an international software development team, an IT services project manager, and, most recently, as a Data Protection Officer. His writing has been published by  howtogeek.com, cloudsavvyit.com, itenterpriser.com, and opensource.com. Dave is a Linux evangelist and open source advocate.
Read Full Bio »