[Learn Hugo] Develop, Stage and Prod Configurations
Tags: hugo, jamstack, tutorial, netlify
Published: 2020-10-07 21:56:43

**Welcome back!** 

In the previous tutorials we talked about the differences between [dynamic and static websites](https://dev.to/aakatev/hugo-getting-started-with-static-websites-3pbb), introduced Hugo, and its typical [project structure](https://dev.to/aakatev/learn-hugo-project-structure-14bp).

Today we will talk about something really important - managing configurations for multiple environments. Yes, we are jumping right into this topic without talking about the layouts and templates! Why? Well, at some point you want your website to be available on the World Wide Web. Which means you will have to put it on a hosting. Depending on the hosting provider, there could be numerous things that should be configured differently compare to the computer you develop on.

Instead of thinking about the deployment last, when the website already have grown big, why don't we establish some great practices straight away?

## Deployment Environments

For a short time, I want to pause talking about Hugo, and cover the concept of having separate environments.

Typical software development workflow consists of more than one environment to make development cycles of a software application smoother and hassle free. The model usually consists of development, staging and production environments. Multiple environments suppose to help developers of the application at various phases, such as development, testing and releases.

For different projects, these terms can mean different things. For a hobby website the development environment is on the developer computer, while for the bigger projects it is distributed between multiple servers. It is common for staging and production to be identical, with the main difference being a presence of the real user data. 

## Environment Configurations in Hugo

Getting back to Hugo, and let's jump right into coding! I will continue working on the `hello-world` project from the previous tutorials. You can create a new project with `hugo create site` command, since we won't really reuse any of the existing code.

First thing, let's add (or create if started a new project) the following to `layouts/index.html`:

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta 
      name="viewport" 
      content="width=device-width, initial-scale=1">
    <title>{{ .Title }}</title>
    <link 
      rel="stylesheet" 
      href="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha2/css/bootstrap.min.css" 
      integrity="sha384-DhY6onE6f3zzKbjUPRc2hOzGAdEf4/Dz+WJwBvEYL/lkkIsI3ihufq9hk9K4lVoK" 
      crossorigin="anonymous">
  </head>
  <body class="d-flex text-center text-white bg-dark" style="font-size: 1.5em;">
    <div class="container w-100 pt-5 mt-5 mx-auto flex-column">
      <h1>Welcome to {{ .Title }}!</h1>
      The website is served at {{ .Site.BaseURL }}
    </div>
  </body>
</html>
```

If you feel lost looking at all the `{{ ... }}` it is totally  fine. It is called templating. We  will cover it in great details in the coming posts. For now just think of it as a way to variablize a piece of HTML. 

Start Hugo development server (`hugo server`), and navigate to `http://localhost:1313`. You should see the following: 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/brlccnqjy36qpmqrc1xk.png)

If you open the `config.toml` it becomes clear where the `My New Hugo Site` part is coming from. There is also `baseURL` property which let you set the domain name for the website. This one can be confusing. When you use the development server the `baseURL` property gets partially overwritten. Read more about it [here](https://discourse.gohugo.io/t/confusion-with-baseurl/12125/3).

By using the configuration files, you can easily manage Hugo project in various stages of the development.

## Development, Staging and Production

Let's look at some real world example. Suppose a website have three environments: development, on a local machine; staging, on Github Pages; and production, on Netlify. How would the configuration for this particular website look? 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/tjyi2uiqh5tcpnz98ly0.png)

Well, the only way to tell is to create such a website! This is not a tutorial on how to deploy a website to Netlify or Github Pages, so excuse me rushing through some of the steps. The point I want to make here is how easy it is to manage configuration with Hugo out of the box.

First, let's look at the development config, **config.toml**:

```toml
baseURL = "/"
languageCode = "en-us"
title = "Development Environment"
```

Easy.

Move on to staging. I will create a GitHub repository, and called it `learn-hugo`. You are free to call it however you want. My GitHub account name is `aakatev`, so the address for my staging website is `https://aakatev.github.io/learn-hugo/`. The usual schema is `https://<username>.github.io/<repo-name>/`. GitHub Pages serves files from `docs` directory, so we should take it into account.

Considering all this, here is my **config-stage.toml**:

```toml
baseURL = "https://aakatev.github.io/learn-hugo/"
languageCode = "en-us"
title = "Staging Environment"
publishDir = "docs"
```

In order to deploy our staging version, the website has to be built locally, and pushed on GitHub. 

Before this moment, we have always been using the default configuration file. Hugo knows about `config.toml`. However, now that the name is different, we have to provide `--config` flag in order to tell Hugo which config to use:

```sh
hugo --config config-stage.toml
```

After the website is pushed into the repo, it will automatically be deployed to GitHub Pages.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/l1itbqa1pjcwa7ci0czq.png)

Finally, our production environment. Netlify comes with CI/CD for static websites by default. Connect your existing GitHub repository, and provide minimum configuration:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/qwfdcculsa9up1kr237s.png)

The default app name generated by Netlify is pretty random. You can always change it, but in my case I decided to leave it as is - `dazzling-curran-c212c7`. The website domain name can be derived as `<netlify-app-name>.netlify.app`, and here is the **config-prod.toml**:

```toml
baseURL = "https://dazzling-curran-c212c7.netlify.app/"
languageCode = "en-us"
title = "Production Environment"
publishDir = "public"
```

Once deployed, the production version should look like so:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ewaofdk24sf84hc3l9ft.png)

## Round Up

Again, this example was more for illustration purposes rather than actual tutorial. That said, in case you do want to try  it out yourself, the complete code is on my [GitHub](https://github.com/aakatev/learn-hugo).

One last thing before I let you go. Although we used configuration files for this project, Hugo allows developers to separate configs by directories.

For example, the config directory can have the following layout:

```sh
├── config
│   ├── _default
│   │   ├── config.toml
│   ├── production
│   │   ├── config.toml
│   │   └── extra.toml
│   └── staging
│       ├── config.toml
│       └── extra.toml
```

Note, the `_default` sub-directory. In Hugo, it is a special name that is pretty self explanatory. This directory will be used in case no `--configDir` flags is provided.

That's it for today! Hopefully, you learned something new. Next time we will talk about Hugo layouts and templates. 

**Stay tuned!**