How to build a fast static website using Hugo and AWS

It’s quite rare nowadays, but time to time I am entering sites which loads extremely fast. It feels like I have just switched tabs in my browser, but in reality, I have fully loaded a completely new website in such speed that I don’t even notice the load time.

Ok. I wanted to build one too.

So that’s what I have done…

Defining goals

First things first. What do we want to achieve?

I hate waiting or making others wait.

So that’s why I want to be certain that when someone visits my site it’s fastest that I can deliver.

Then what’s fast enough?

Blinking is fast. How fast we blink? This suggests that average blink takes 350ms.

Two blinks sound like a short time for me. Let’s load a site in a mere two blinks.

Finding right benchmarks

To a certain limit, it’s healthy to be obsessed with benchmarks.

David Gilbertson has built the fastest site in the world. In terms of speed, let’s try to get as close to him as we can.

David was using for benchmarking speed of his site. To have a fair comparison, we will use the same.

And to test usability we will be using Lighthouse which is a primary tool while building a progressive web app.

Setting up environment


To host the site we will be using Amazon Web Services (new users get “Free tier” package which lets to use lots of services for free for a year). Specifically:

To create and manage content of the site we will be using Hugo which is “the world’s fastest framework for building websites”.

To connect AWS and Hugo in a painless way we will use s3_website


First let’s install some things:

Setting up the site

Now follow these steps:

  1. Enter terminal and create an initial Hugo site by calling hugo new site site-name, enter the directory and install the desired theme from and run hugo to generate static content.
  2. Register/Login in AWS Console and go to AWS IAM console. Create a new user that has Full Permissions on S3 and CloudFront services.
  3. Inside site directory initialize s3_website with s3_website cfg create. Open the generated file s3\_website.yml and place credentials from AWS to s3\_id and s3\_secret. Add your site domain name ( to s3\_bucket, set site: public.
  4. Now run s3_website cfg apply to initialize required services on AWS. The output will provide you with the CloudFront URL on which you will be accessing the site. Copy that URL and paste to config.toml to change your base URL.
  5. Now to upload your content just run s3_website push (use this command every time you want to upload new content). It takes ~15 minutes to initialize so be patient.
  6. Go to CloudFront and make sure your distribution has status Deployed. Then use Route53 to attach your existing domain or buy a new one from Amazon.
  7. To assign the domain to a CloudFront distribution, in Route53 create new Hosted Zone and for this zone add two CNAME records. Leave one empty and another one name www. Select yes at has alias and from the list choose your CloudFront distribution. Then change your domain DNS records to match Name Servers defined in Route53.
  8. Finally, use AWS Certificate Manager to create an SSL certificate for your domain.


Time for benchmarks!

Open your website, press on Lighthouse extension and generate the report.

If you don’t see red colours - then, well… It’s not the worst!

Anyway, the goal is to make everything green!

If you have followed the instructions, you should see quite few problems. Let’s see how to fix them:

  1. Configure manifest.json:
    • Navigate to static folder and download manifest.json template wget Then add link to it into your index head section <link rel="manifest" href="/manifest.json">.
  2. Configure a Service Worker:

    • For this we will use an NPM package sw-precache so let’s install it.
    • Then run node ./node_modules/sw-precache/cli.js --root=public --static-file-globs='public/**/*.{js,html,css,png,jpg,gif,eot,svg,ttf,woff,woff2,otf}'
    • Add the following code to your index file in head section:
      if ('serviceWorker' in navigator) {
      window.addEventListener('load', function() {
      navigator.serviceWorker.register('service-worker.js').then(function(reg) {
      reg.onupdatefound = function() {
      var installingWorker = reg.installing;
      installingWorker.onstatechange = function() {
        switch (installingWorker.state) {
          case 'installed':
            if (navigator.serviceWorker.controller) {
            console.log('New or updated content is available.');
            } else {
            console.log('Content is now available offline!');
            case 'redundant':
            console.error('The installing service worker became redundant.');
            }};};}).catch(function(e) {
            console.error('Error during service worker registration:', e);
  3. Redirect HTTP to HTTPS:

    • Go to AWS CloudFront panel, press on your distribution, navigate to Behaviours section, select default behaviour and press Edit.
    • In Viewer Protocol Policy select Redirect HTTP to HTTPS and save. It will take some time to update.
  4. Match address bar with your brand colors

    • Add theme-color tag to head section <meta name="theme-color" content="#292b2e">. Choose any color you like in content part.
  5. Configure custom splash screen

    • As defined in manifest.json create .png files of your logo inside static/img/icons directory with the defined sizes.

And that’s it!

You may have some custom optimizations to do (like optimizing images). But if you have started with the basic template, if you would run the lighthouse right now, you should see all tests passed.

At this point, we have a fast static website which is also a 100% progressive app.


Everything is green! Time to test the speed.

Open and test your website.

And remember the fastest site in the world? Test this also and compare it with your site.

I got (first view):

The site in reality is much faster.

Let’s convert the result to blinks…..

Less than 2 blinks for our site to load.

Achievement unlocked!


That’s it. We have a site that loads on users screens in less than two blinks. From here you can use the power of Hugo to create content and easily upload if not to the fastest, then definitely to one of the fastest sites out there.

If something went wrong - contact me, I will help to solve your problems and will update this tutorial so others would not fail in the future.

Stay strong!