How to host a Hugo site on the Netlify CDN for free
Hosting a Hugo site on Netlify is free (and awesome) if it’s a personal website. Here’s how to set it up and deploy.
Updated November 20, 2022Tested with Hugo version 0.106.0
In this tutorial, I’ll show you how to get your Hugo site hosted on Netlify.
Hosting is free for personal websites.
Let’s dive in!
How to set up a Hugo site on Netlify hosting
Step 1: Sign up for Netlify
If you haven’t already, you can sign up for Netlify here.
I don’t make any money from this; I just recommend tools and services that I myself use and enjoy.
Step 2: Add your domain name to Netlify
2a) Log in to your Netlify account if you haven’t already.
2b) Head to the “Domains” tab.
2c) Click the “Add or register domain” button:
2d) Add your domain name (or intended domain name—you can have Netlify purchase it for you).
2e) Hit the green “Verify” button:
If you already own your domain, you’ll see the screen below. (If you don’t own your domain, and want Netlify to purchase it for you, this tutorial doesn’t cover that yet. I may add it in the future.)
2f) Hit the green “Yes, add domain” button:
Next, you’ll see the screen below.
There’s no need at this stage to add DNS records.
You can always do this later, for example, if you want to set up MX records for email.
However, for now:
2g) Hit “Continue”
Finally, you’ll see the screen below. Keep it open in your browser as you’ll need it in a second.
Step 3: Log in to your domain registrar and update the nameservers
Every domain registrar’s interface is generally a bit different, so I won’t provide a screenshot here.
However, it should be relatively straightforward to find out how to change the nameservers for your domains at your provider (e.g. NameCheap, GoDaddy, VentraIP etc).
You’ll need to update the nameservers to the ones you got in the previous step of this tutorial—which may be different to the ones in my screenshot above.
Once you have made these changes, it may take several hours to propagate through the DNS network.
Step 4: Prepare your site for deployment to Netlify by creating a “netlify.toml” file
While you’re waiting for the nameserver changes you made in Step 3 to propagate, you can prepare your site for deployment to Netlify from your GitHub, GitLab or Bitbucket account.
When you deploy a Hugo site to Netlify, you can choose how you want it built. You can choose whether you want:
- your site minified or unminified
- expired content published or not
- future-dated posts published or not
… and many other options.
There are two ways to convey this to Netlify:
- Specify your Hugo build requirements in the Netlify UI
- Specify your Hugo build requirements in a file named
netlify.toml
which lives in your Hugo repo and is thus version controlled as well as being easier to eyeball.
As you may have inferred from the way I phrased the two choices, I prefer and recommend the second option.
If you want to set your Netlify config up this way too, you’ll need to create a file named netlify.toml
in the root of your Hugo site. (It will live at the same level as your config.toml
, in other words.)
And here’s the relevant part of my netlify.toml
:
[context.production.environment]
HUGO_VERSION = "0.106.0"
HUGO_ENV = "production"
[context.deploy-preview.environment]
HUGO_VERSION = "0.106.0"
[build]
publish = "public"
command = "hugo --minify --buildFuture"
As you can see, my build command is "hugo --minify --buildFuture"
.
This means I have Hugo minify my content, which makes it a bit faster to load, and I also have it build future-dated content.
This is because my timezone in Australia is ahead of Netlify’s in San Francisco, and I don’t want to run into any issues with content not getting published.
If I’m not ready for a post to go live then I do one or more of the following:
- Commit it to a branch other than
main
- Ensure it has
draft: true
in its YAML front matter - Don’t commit until it’s ready (my repos are all redundantly backed up in iCloud)
Step 5: Deploy your site to Netlify
a) Head to the “Sites” tab
b) Hit “New site from Git”
You’ll see the screen below.
c) Choose your Git provider (GitHub, GitLab or Bitbucket)
d) You’ll then be asked to sign in to your Git provider via a pop up window (not shown here).
I use GitHub so the rest of this tutorial will focus on that. It should be pretty similar for GitLab or Bitbucket, though.
e) You can then choose the repository containing your Hugo site.
f) If you don’t see the repo in the list, you’ll need to configure the Netlify app in your Git provider (e.g. GitHub). You can click the green text link named “Configure the Netlify app on GitHub” to do so.
g) Choose your branch (if not master
or main
).
h) I leave out the Hugo build command and the location of my site (usually /public
), as I prefer to specify these in a netlify.toml
file which lives at the root of my repo, as specified earlier in this tutorial.
i) Hit “Deploy” and you’re done! Once your DNS changes have propagated, your site will be live on Netlify.
Compression is automatic with Netlify
You don’t need to do anything to enable asset compression with Netlify. In Netlify’s own words:
It just works.
That phrase has become immortal, it seems.
Depending on the asset type (HTML, CSS, JS, SVG etc), Netlify uses either gzip or Brotli compression.
For HTML, CSS and JavaScript, Netlify uses Brotli compression rather than gzip.
Here’s why.
Quoting an Akamai study (which appears to have since been removed), Netlify states:
JavaScript files compressed with Brotli are 14% smaller than gzip.
HTML files are 21% smaller than gzip.
CSS files are 17% smaller than gzip.
That’s good enough for me! Brotli compression is accepted by pretty much all browsers.
For SVG files, Netlify uses gzip compression.
I confirmed this by testing my own site.
When I used Developer Tools to inspect the MoonBooth homepage in Microsoft Edge—using an InPrivate window to avoid the effect of browser extensions—I noticed that:
- The HTML document was compressed with Brotli
- The CSS stylesheet was also compressed with Brotli
- The
logo.svg
andplanets.svg
files were compressed with gzip - The
favicon.svg
was not compressed at all (at 462 bytes, perhaps it would have been made larger by doing so due to the presence of thecontent-encoding
header).
Be aware that browsers recognise Brotli compression, but speed tester Pingdom doesn’t
An interesting fact I discovered recently is that one of the most well-known speed tests—Pingdom—does not recognise Brotli compression and thus marks you down. This is not an issue for SEO—as touched on above, Chrome and Chromium browsers such as Microsoft Edge, Opera and Brave do accept Brotli compression, and in fact, it was developed at Google! If anyone at Pingdom is reading this, I’d encourage you to add Brotli compression to your speed check.
How to 301 redirect your default Netlify subdomain to your primary domain
When you first host a site on Netlify, your site will automatically be published on a Netlify subdomain of the form example.netlify.app
.
You can’t eliminate this Netlify subdomain (although you can rename it in the UI). What you can do—and what I recommend you do from an SEO perspective—is 301
redirect it to your primary domain.
The only way to do this is in your /static/_redirects
file. When I tried to put this redirect in my /netlify.toml
file, it didn’t work. Note: I do keep all my other redirects—for example, if I combine two blog posts—in netlify.toml
, and they work just fine.
So, in /static/_redirects
, add this:
# Redirect default Netlify subdomain to primary domain
https://example.netlify.app/* https://example.com/:splat 301!
Some points on the above:
- Obviously you would change
example.netlify.app
to match your Netlify subdomain; similarly, you would changehttps://example.com
to match your primary domain. - The
/*
and/:splat
you see above work together to create a wildcard redirect. Soexample.netlify.app/my-awesome-blog-post/
will 301 redirect toexample.com/my-awesome-blog-post/
, and so forth for every piece of content (including the home page). - Make sure you use the exclamation mark on the end of the
301
, as that is how Netlify forces redirects even when the original file (atexample.netlify.app/*
) exists. - I recommend a 301 redirect, as per the code sample above, unless you have a very good reason to use a 302 redirect.
- You don’t need to handle the non-
https
version of the.app
Netlify subdomain (or the old.com
format if you’re a longstanding Netlify user), as Netlify 301 redirects those to thehttps
version of the.app
subdomain automatically.