Generating a Static Site with Hugo + Netlify in 15 minutes
Tags: netlify, hugo, staticsitegenerator
Published: 2020-02-21 14:10:55

---
title: Generating a Static Site with Hugo + Netlify in 15 minutes
published: true
description: In this tutorial we show how you can generate a static site with Hugo and Netlify in an easy and fast way.
tags: netlify, hugo, static site generator
canonical_url: https://blog.risingstack.com/static-site-generator-hugo-netlify/
cover_image: https://blog.risingstack.com/content/images/2020/01/static-site-generation-hugo-netlify.png
---

In this article, I’m going to show how you can quickly generate a static site  with Hugo and Netlify in an easy way.


## What are static site generators, and why do you need one?

Simply put, a static site generator takes your content, applies it to a template, and generates an HTML based static site. It’s excellent for blogs and landing pages. 

Benefits:
* Quick deployment
* Secure (no dynamic content)
* Fast load times
* Simple usage
* Version control

So, what are the popular options in terms of static site generators?

* Gatsby (React/JS)
* Hugo (Go)
* Next.js (React/JS)
* Jekyll (Ruby)
* Gridsome (Vue/JS)

These are the most starred projects on GitHub. I've read about Hugo previously, and it seemed fun to try out, so I’m going to stick with Hugo.


## What is Hugo?

The official website states that Hugo is the world's fastest static website engine.

![hugo static site generator](https://blog.risingstack.com/content/images/2020/01/hugo-static-site-generator.png)

We can confirm that it’s really fast. Hugo is written in Golang. It also comes with a rich theming system and aims to make building websites fun again. 

Let’s see what we got here.


### Installing Hugo

Mac:
```bash
brew install hugo
```

Linux:
```bash
sudo apt-get install hugo

or

sudo pacman -Syu hugo
```

To verify your install:
```bash
hugo version
```


### Using Hugo

Create a new project:
```bash
hugo new site my-project
```

Add a theme for a quick start. You can find themes [here](https://themes.gohugo.io/).

```bash
cd my-project
git init
git submodule add https://github.com/budparr/gohugo-theme-ananke.git themes/ananke
```

Add the theme to the config file.

```
echo 'theme = "ananke"' >> config.toml
```

Add some content.

```bash
hugo new posts/my-first-post.md
```

It should look something like this:

```
---
title: "My First Post"
date: 2020-01-05T18:37:11+01:00
draft: true
---

Hello World!
```

There are lots of options (tags, description, categories, author) you can write to the front matter details.

You can read more about the details [here](https://gohugo.io/content-management/front-matter/).

Take a look at what we made:

```bash
hugo server -D
```

Open `http://localhost:1313`


### Understanding Hugo’s directory structure

```
.
├── archetypes
├── assets (not created by default)
├── config.toml
├── content
├── data
├── layouts
├── static
└── themes
```

* **archetypes**:  Archetypes are content template files that contain preconfigured front matter (date, title, draft). You can create new archetypes with custom preconfigured front matter fields.
* **assets**: Assets folder stores all the files, which are processed by Hugo Pipes. (e.g. CSS/Sass files) This directory is not created by default.
* **config.toml**: Hugo uses the `config.toml`, `config.yaml`, or `config.json` (if found in the site root) as the default site config file. Instead of a single config file, you can use a [config directory](https://gohugo.io/getting-started/configuration/#configuration-directory) as well to separate different environments..
* **content**: This is where all the content files live. Top level folders count as content sections. If you have `devops` and `nodejs` sections, then you will have `content/devops/first-post.md` and `content/nodejs/second-post.md` directories.
* **data**: This directory is used to store configuration files that can be used by Hugo when generating your website.
* **layouts**: Stores templates in the form of `.html` files. See the `Styling` section for more information.
* **static**: Stores all the static content: images, CSS, JavaScript, etc. When Hugo builds your site, all assets inside your static directory are copied over as-is.
* **themes**: Hugo theme of your choice.


## Styling our static site

Remember, we applied a theme before. Now, if we inspect the `themes` folder, we can see the styling files.

But beware!

> **DO NOT EDIT THESE FILES DIRECTLY**.

Instead, we will mirror the theme directory structure to the root `layouts` folder.

Let's say I want to apply custom CSS to the theme.

The theme has a `themes/theme-name/layouts/partials` folder, where we can find some HTML templates (header.html, footer.html). Now we will edit the `header.html` template, so copy the content from this file to `layouts/partials/header.html` and be careful to create the same directory structure like the theme's into the root `layouts` folder.

```
layouts/partials/header.html

themes/theme-name/layouts/partials/header.html
```

Create a custom CSS file: `static/css/custom-style.css`.

Add the custom css file to `config.toml`:

```
[params]
 custom_css = ["css/custom-style.css"]
```

Open `layouts/partials/header.html`:

Add this code inside the `<head>` tag:

```
{{ range .Site.Params.custom_css -}}
   <link rel="stylesheet" href="{{ . | absURL }}">
{{- end }}
```

Now you can overwrite CSS classes applied by your theme.


## Deploying our static site to Netlify

One of the benefits of a static site is that you can deploy it easily. Netlify or AWS S3 is a very good choice for hosting a static site. Let’s see how to deploy it to Netlify.

Requirements:
 - Netlify account
 - Github repository


### What to do on Netlify

.1. Create a git repository

.2. Create a `netlify.toml` file into the root of your project with the content below.

```
[build]
publish = "public"  // default hugo build folder
command = "hugo --gc --minify" // hugo build command

[context.production.environment]
HUGO_VERSION = "0.62.1"
HUGO_ENV = "production"
HUGO_ENABLEGITINFO = "true"
```

.3. Now, if you push your code to Github, Netlify will deploy the site, and blogging shall start.

.4. Connect Netlify and your Git repository

.5. Build and deploy

You can also take a look at the [Hugo official Netlify hosting details](https://gohugo.io/hosting-and-deployment/hosting-on-netlify/) for further information.


### AWS S3 + CI

We will be using Terraform to create an S3 bucket that will host our static site. I assume you have an AWS account.

Create an `s3_bucket.tf` file in your project and insert the content below to it:

```
resource "aws_s3_bucket" "my-static-site" {
  bucket = "my-static-site"
  acl    = "public-read"
  policy = <<POLICY
{
  "Version":"2012-10-17",
  "Statement":[
    {
      "Sid":"PublicRead",
      "Effect":"Allow",
      "Principal": "*",
      "Action":["s3:GetObject"],
      "Resource":["arn:aws:s3:::my-static-site/*"]
    }
  ]
}
POLICY

  website {
    index_document = "index.html"
    error_document = "index.html"
  }
}
```

Then, folllow these steps:

* execute `terraform init`

* insert the following code snippet
```
export AWS_ACCESS_KEY_ID="anaccesskey"
export AWS_SECRET_ACCESS_KEY="asecretkey"
export AWS_DEFAULT_REGION="us-east-1"
terraform plan
```

* execute `terraform apply`

This will create a public readable AWS S3 bucket, which will host the static site.

Now we have to take care of building the static site on our own: we need a CI tool.


### Setting up CircleCI for continuous integration

At RisingStack, we’re usually using CircleCI for these kinds of tasks. Let’s set up the build process.

Create the following files in the project root: `.circleci/config.yml`

Apply the following code to `config.yml`:

```
version: 2
jobs:
  build:
    docker:
      - image: cibuilds/hugo:latest
    working_directory: ~/hugo
    environment:
      HUGO_BUILD_DIR: ~/hugo/public
    steps:

      # install git
      - run: apk update && apk add git

      # checkout the repository
      - checkout

      # install git submodules for managing third-party dependencies
      - run: git submodule sync && git submodule update --init

      - run:
          name: install AWS CLI (first install pip, the Python package manager)
          command: |
            apk add --update python python-dev py-pip build-base
            pip install awscli

      # build with Hugo
      - run: HUGO_ENV=production hugo -v -d $HUGO_BUILD_DIR
 
      - run:
          name: test our generated HTML files
          command: |
            htmlproofer $HUGO_BUILD_DIR --allow-hash-href --check-html \
            --empty-alt-ignore --disable-external

      # `deploy` step: identical to a `run` step, but uses only one container:
      # /docs/2.0/configuration-reference/#deploy 
      - deploy:
          name: deploy to AWS
          command: |
            if [ "${CIRCLE_BRANCH}" = "master" ]; then
              aws s3 sync $HUGO_BUILD_DIR \
              s3://my-static-site --delete
            else
              echo "Not master branch, dry run only"
            fi
```

Note: To add AWS credentials, locate the AWS Permissions link under the Permissions section in CircleCI.


## Moving forward with Hugo

Hugo offers so much more you should know about. Discover the official [documentation](https://gohugo.io/documentation/) here.

![Unlimited power](https://media1.giphy.com/media/3o84sq21TxDH6PyYms/giphy.gif?cid=790b7611f96ab1767b958080a2f06b34e1ed402337c52d48&rid=giphy.gif)

If you'd like to check out the very simple page I created, head over to https://bmz-codez.com/

In case you professional software development services, feel free to reach out to us using our website: https://risingstack.com/nodejs-development-consulting-services