Build & Deploy a Site with Hugo & Firebase
Tags: firebase, hugo, website, webdev
Published: 2023-10-24 13:31:56

It’s not uncommon to find content creators who choose to have their content on personal blogs/websites. Usually, a go-to solution would be to use a CMS (Content Management System) like [WordPress](https://wordpress.org/) or [Wix](https://www.wix.com/).

However, building a web application with any of these technologies is restrictive due to their monolithic design (tight coupling between client and server). It’s harder to manage and scale these kinds of applications. Some of the likely drawbacks of these CMS applications include:

- Tight coupling between components (making it harder to test components individually).

- Large and complicated codebase: Making it hard for collaboration.

- Less reusability.

- It does not follow the [SRP (Single Responsibility Principle)](https://en.wikipedia.org/wiki/Single-responsibility_principle).

---

## Jamstack to the rescue

With the rise of [Jamstack](https://jamstack.org/), building web applications that are fast, lighter, decoupled, and easily maintainable is just a couple of tools away. If you’re wondering what Jamstack is all about, I’ve written a practical guide here to get you started:

{% embed https://devjavu.space/post/a-practical-introduction-to-jam-stack/ %}

With Jamstack, we can use [Static Site Generators](https://jamstack.org/generators/) like Hugo to generate and deploy a site on a CDN like [Firebase Hosting Service](https://firebase.google.com/docs/hosting) or [Netlify](https://www.netlify.com/).

---

## What you’ll need

- [Firebase CLI](https://firebase.google.com/docs/cli)

- [Hugo CLI](https://gohugo.io/installation/)

- A Firebase account

- Basic knowledge of CLI ( Command Prompt or Terminal )

## Hugo

Hugo is a popular open-source static site generator that helps us quickly scaffold simple websites.

## Installation (Mac)

To get Hugo installed on your Mac Operating System, you must ensure you have [Homebrew](https://brew.sh/) installed. Homebrew is a package manager for macOS and Linux.

If you do not already have Homebrew installed, you can install it on macOS with a single command. Open up your terminal and paste this:

```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

Once the installation is complete, you should be able to access the brew CLI. Verify that you have Homebrew installed by typing: `brew`


![Homebrew verification](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xv7s4sbumrq0ebpvbh35.png)

That’s about all you need to install Hugo on your macOS.

## Installation (Windows)

- [Binary Installation](https://github.com/gohugoio/hugo/releases)

- [Chocolatey](https://chocolatey.org/)

The Binary installation is perhaps the easiest way to install Hugo CLI on your system. You can download the appropriate version for your platform from [Hugo Releases](https://github.com/gohugoio/hugo/releases). Once downloaded, you need to unzip and install it. The binary can be run from anywhere, so you won’t need to install it in a global location.

## Chocolatey

Chocolatey is the package manager for Windows operating systems, the same way you have Homebrew for macOS. You can find the installation guide here:

{% embed https://chocolatey.org/install %}

Once installed, you can simply install Hugo with this command:

```bash
choco install hugo -confirm
```

## Installation (Linux)

You can also use the [binary installation](https://github.com/gohugoio/hugo/releases) to get Hugo on your Linux machine. Alternatively, you can install Hugo with [Snap](https://snapcraft.io/).

First, you need to install the Snap CLI tool.

```bash
sudo apt update
```

```bash
sudo apt install snapd
```

```bash
snap install hugo
```

Great! Now, you should have Hugo installed on your system. Next, we need to create a Firebase account (if you don’t already have one).

---

## Firebase
Head over [here](https://console.firebase.google.com/) and create an account. Once you’re logged in, you'll need to create a new Firebase project.


![New project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1xkhftr6t3d1ixazqiyz.png)

Give your project a name like so:


![Project name](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0mfqum6am6vrbdjd1u7e.png)

We do not need to enable Google Analytics for this project, so you can comfortably turn that off:


![Google analytics](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fobckwpp28csc04eibs1.png)

Grab a coffee while your project is being generated. ☕️

---


![New project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5xe8pi98s2l501j4v0vq.png)

Your project should be ready now. Click “**Continue**” to proceed to your Firebase dashboard.

Firebase offers a handful of services that help you build and deploy mobile and web applications easily. One such service is the Firebase hosting service. This is the service we will be using.

## Firebase CLI

Now that you have your Firebase account set up and have successfully created a Firebase project, we can proceed to install the [Firebase CLI](https://firebase.google.com/docs/cli). This command-line interface allows us to perform certain Firebase actions from our machine via the terminal.

- Windows: Download the latest binary for Firebase tools [here](https://firebase.tools/bin/win/instant/latest)

- macOS / Linux: For macOS or Linux users, you can run the auto-install script. The script will automatically detect your operating system and install the latest Firebase CLI release.

```bash
curl -sL https://firebase.tools | bash
```

## Via NPM

It is also possible to install Firebase CLI via [NPM](https://npmjs.com/) (Node Package Manager) if you already have [Node](https://nodejs.org/en/) installed.

```bash
npm install -g firebase-tools
```

Once the installation is successful, you should have the Firebase command available from your terminal.


![Terminal](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9btzjav9hhgpp0946gu7.png)
-

---

## Generate Hugo Site

Next, we need to generate our site with Hugo CLI. Open up your terminal/command prompt and type:

```bash
hugo new site site_name
```

You can decide to give your site whatever name you wish. A new folder will be created with the name you specified.


![Folder](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vcwxw2dsyvb44bafo1ov.png)

Hugo CLI scaffolds a project directory structure with empty subfolders; let’s take a closer look at the generated folder structure.

I’ll open up the application in VSCode. From the terminal, you can type:

```bash
code .
```


![Another folder](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5qx720oyhvidathaced1.png)


The folders above should be empty when generated. Let’s break down what each folder serves.

> Most of the information about folder structure can be found [here](https://gohugo.io/getting-started/directory-structure/).

- **Archetypes**: In Hugo, **front matters** are metadata that holds tiny information about our site content (date, title, draft). Archetypes contain custom preconfigured front matters.

- **Content**: All content for your website lives inside this directory. Each top-level folder in Hugo is considered a [content section](https://gohugo.io/content-management/sections/). For example, if your site has three main sections — `blog`, `articles`  and `tutorials`—you will have three directories at `content/blog`, `content/articles` and `content/tutorials`.

- **Data**: This directory is used to hold configuration files used by Hugo when generating your website. You can write configurations in JSON, YAML, or TOML.

- **Layout**: This folder is used to store templates in the form of “.html” files that specify how views of your content will be rendered into a static website.

- **Static**: Stores all the static content: images, CSS, JavaScript, etc.

---

Now that we have a basic understanding of the folders that were generated, we can move on.
The Hugo CLI only generates a skeletal structure for you. It is void of theming and content (all the folders are empty). We, however, have a whirlpool of [community themes](https://themes.gohugo.io/) we can install. Hugo themes can be installed as git submodules.

{% embed https://themes.gohugo.io/ %}

To install a Hugo theme from your terminal within your Hugo root project directory, type:

```bash
git init$ git submodule github_url
```

I’m going to install the [Ananke](https://themes.gohugo.io/gohugo-theme-ananke/) theme:


![Ananke theme](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eogpub4kv9e2pj4fpcyz.png)

First, we initialize our project folder as a git repository, then install the theme as a submodule.

```bash
git init
```

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

The Ananke theme would be cloned into the directory we specified (`/themes/ananke/`). Let’s take a look at what the theme directory contains.


![Directory](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w7i7p03nruxr75miz4i3.png)

There are two ways to get started using this theme:

- Using the example content provided by the theme

- Creating your content

## Using the example content

In this case, from the theme directory structure, what we are interested in is the “**exampleSite**” subdirectory. It would serve as a template to get started quickly with some dummy content. Firstly, what you need to do is copy the content of the “**exampleSite**” directory into your root directory. You can either do this manually (CTRL + A & CTRL + C & CTRL + V 👴🏼)

or from the terminal:

```bash
cp -R ./themes/ananke/exampleSite/* ./
```

This would add some folders and files (about, post, _index.md) in your “content” folder in your root directory.

> This copy would also replace your “config.toml” file. PS: This is a very crucial configuration file.

You need to edit the **config.toml** file to specify the correct theme name and theme directory so the Hugo CLI knows what and where to look.

```toml
theme = "ananke"themesDir = "./themes"
```

Once that’s done, you can save and start the Hugo server:

```bash
hugo server
```


![Terminal](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qtpe73bjxa20em6z8zs0.png)


You can navigate `localhost:1313` to view your site.


![Hugo theme](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iiwlaozkq182h8lxco1y.png)

> The Hugo has support for [live-reload](https://gohugo.io/getting-started/usage/#disable-livereload), so you don’t need to reload pages when you make a change.

Let’s try changing the header text. Open “**_index.md**”; you should see the title front matter value:


![Change title](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s19459rfet670g2q7m4f.png)

Try changing it to “My Hugo Test Site” and check the site in your browser.


![Rename](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w12xzebjuu6ty2qeqv8c.png)

You can keep making changes and creating new pages/posts from here. You can check out the documentation to learn [more](https://gohugo.io/getting-started/usage/) about Hugo CLI.

## Creating your content

You don’t need to copy the content of the example site directory in this case. Open the “**config.toml**” file in your project root directory, set the “theme” value to Ananke, and also set the theme directory.

```toml
theme = "ananke"
themesDir = "./themes"
```

Your configuration file should look something like this:


![Configuration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pvz5wvkc90rqxn63pnh5.png)


Once that’s done, you can create your first post/page using the Hugo CLI.

```bash
hugo new index.md
```

This command generates a new file called “**index.MD**” (markdown extension) in your contents directory. You can open this file and add some text.



![File](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fglvd0i7fka9i9ztip8b.png)

> Notice the front matter at the top (title, date, draft)

Save this file and spin up the Hugo server again.

```bash
hugo server -D
```

Notice here we have a `-D` flag as opposed to the first time we started the server. This flag enables drafts.

> Draft? What does that mean?

When you have a newly generated page/post, it is automatically in drafts and will not be publicly available until you “publish” it ( in this case, set draft to “false”). If, however, you do not wish to publish just yet but would still like to work on the page and see your changes, you can start the Hugo server with the -D flag.

> Note: All public pages should have the draft value set to false

Great! Now we have our Hugo site ready. Next step — deployment.

---

## Deploying to Firebase

We need to first generate the static files for our site using the `hugo` command in the root directory.

This generates the static files for your website and copies them into the `public/` directory by default, although you can customize the output directory in your [site configuration](https://gohugo.io/getting-started/configuration/) by changing the `publishDir` field (we won’t be doing that). From your terminal, type:

```bash
hugo
```

Once your static files have been generated, initialize Firebase from your root directory:

```bash
firebase init
```

You’ll be presented with options to choose from. These options are Firebase services; we’ll only be selecting the hosting service. Once you have the arrow on a service, press the spacebar to select it.


![Command line](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zps1iv1nxy9vi9w0io7e.png)

Next, we need to associate the project directory with a Firebase project (remember the project we created earlier from the Firebase web console? Yeah, that one). Choose “Use an existing project”:


![Choose project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/afukijd5kmbeuaxaxztm.png)

You would be presented with a list of existing projects on Firebase. Navigate to the new project we created and select it.


![Select project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9siyqkz58kurrh6cu8ti.png)


Next, you’ll need to set your public directory (This is the directory from which Firebase would publish our site). Since we already know that Hugo CLI generates static files to the public directory, we can simply press the enter key (as Firebase uses “public” by default).


![Default directory](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uk9dlycha2sf7imrfnzb.png)

When asked whether to configure it as a single-page app, Choose No by typing N. If you’re asked whether to overwrite files in the public folder, just choose Yes for now.

![Configure app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1pt7a5xalel8c2dxq314.png)

Your Firebase setup should now be complete.

Next, we’ll regenerate our static files with Hugo CLI and then deploy with Firebase CLI. Type `hugo` from your terminal, then type `firebase deploy`.

```bash
hugo
```

```bash
firebase deploy
```

Your deployment should be successful at this point. Firebase generates a Hosting URL for your site as well. You can copy the URL and open it in the browser to view your site.


![Deploy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oaff0k5kmjap06ce3g9r.png)

You can equally access the site from a **firebaseapp.com** subdomain.

---

**Custom Domain (Extra)**

If you want to go a step further and use a custom domain name for your site, the Firebase console has a section to add a custom domain. From the Firebase console, select Hosting:


![Hosting](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a6rvgh2y7s3t0xcom2gz.png)

Next, click on “Add Custom Domain” and go through the process of setting it up and verifying ownership.

Well, it’s been a long ride. Cheers if you made it this far.

You can find all the project files here:

{% embed https://github.com/MartinsOnuoha/hugo-firebase %}

Cheers ☕️

---