Hugo + Vercel

Static Sites, the name may sound very dull, but it is the best thing if you want to make a simple website that will serve static content. The static sites are often made with JAMStack frameworks (JavaScript, APIs, and Markup) if not completely made from scratch. Few static site generators for JAMStack are Jekyll, Hugo, Next.js, Nuxt.js, GitBook, Hexo, Gatsby, etc. The main goal of JAMStack is to generate all the pages (in HTML / CSS / JS) or content at deploy time. Thus no JAMStack site depends on a particular web server that relies on a backend language.

I chose Hugo because it is faster than any JavaScript-based static site generators (Yes, I’m talking about the bulky node_modules of the JS frameworks). Hugo is written in Go and from the project generation to deployment, it is lightning fast.

Now, without much talk, let’s dive into the step by step guide.

1. Install Hugo

You can follow this link to the official guide to install Hugo.

Installing the hugo-extended package is recommended as it supports Sass / SCSS and many Hugo themes use Sass / SCSS. Sass based Hugo themes won’t work in the basic Hugo installation.

2. Create a new site

The following command will create a new Hugo site in a new directory called mysite.

$ hugo new site mysite

3. Add a theme to the site

Themes are a very important part of Hugo. It can alter the look and feel of the site and can also change the functionality of the site to some extent. Check the Hugo theme gallery @

I am using the hello-friend-ng theme for this site.

$ cd mysite
$ git init
$ git submodule add themes/hello-friend-ng

If you want to edit the theme, go to the GitHub repo and fork it. After committing the changes, we can add the forked repo as a submodule of our Hugo site.

The site directory contents look like this:

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----          05-07-2020 11:22 PM                archetypes
d----          05-07-2020 11:22 PM                content
d----          05-07-2020 11:22 PM                data
d----          05-07-2020 11:22 PM                layouts
d----          05-07-2020 11:24 PM                resources
d----          05-07-2020 11:22 PM                static
d----          05-07-2020 11:22 PM                themes
-a---          05-07-2020 11:23 PM            133 .gitmodules
-a---          05-07-2020 11:31 PM            107 config.toml

Add this line theme = "hello-friend-ng" at the end of the config.toml file.

4. Run the development server

From the mysite directory, run the following command to start a development server to get a preview of the site in localhost. Open the given localhost address given by the Hugo server.

$ hugo server -D
port 1313 already in use, attempting to use an available port
Building sites …
                   | EN
  Pages            |  7
  Paginator pages  |  0
  Non-page files   |  0
  Static files     | 12
  Processed images |  0
  Aliases          |  2
  Sitemaps         |  1
  Cleaned          |  0

Built in 52 ms
Watching for changes in D:\Projects\static_site\mysite\{archetypes,content,data,layouts,static,themes}
Watching for config changes in D:\Projects\static_site\mysite\config.toml
Environment: "development"
Serving pages from memory
Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
Web Server is available at http://localhost:1719/ (bind address
Press Ctrl+C to stop

As our server is running, let’s see what we have got in the browser.

Hugo First Run

5. Configure the theme

In step #3 we added a line in the config.toml file to configure Hugo to use a theme. This file contains various configuration for Hugo. Available configurations are documented here. Most of the Hugo themes comes with an example site. Let’s have a look assuming the present working directory is mysite/.

$ ls -l themes/hello-friend-ng/
total 12
-rwxrwxrwx 1 drake drake  511 Jul  5 23:23
-rwxrwxrwx 1 drake drake  279 Jul  5 23:23
-rwxrwxrwx 1 drake drake 1203 Jul  5 23:23
-rwxrwxrwx 1 drake drake 6869 Jul  5 23:23
drwxrwxrwx 1 drake drake 4096 Jul  5 23:23 archetypes
drwxrwxrwx 1 drake drake 4096 Jul  5 23:23 assets
drwxrwxrwx 1 drake drake 4096 Jul  5 23:23 data
drwxrwxrwx 1 drake drake 4096 Jul  5 23:23 docs
drwxrwxrwx 1 drake drake 4096 Jul  5 23:23 exampleSite
drwxrwxrwx 1 drake drake 4096 Jul  5 23:23 i18n
drwxrwxrwx 1 drake drake 4096 Jul  5 23:23 images
drwxrwxrwx 1 drake drake 4096 Jul  5 23:23 layouts
drwxrwxrwx 1 drake drake 4096 Jul  5 23:23 static
-rwxrwxrwx 1 drake drake  717 Jul  5 23:23 theme.toml
$ ls -l themes/hello-friend-ng/exampleSite/
total 8
-rwxrwxrwx 1 drake drake 4160 Jul  5 23:23 config.toml
drwxrwxrwx 1 drake drake 4096 Jul  5 23:23 content
drwxrwxrwx 1 drake drake 4096 Jul  5 23:23 resources

As we can see, our theme has an example site and It contains a config.toml file. Let’s copy the file to our main site root.

$ cp themes/hello-friend-ng/exampleSite/config.toml config.toml

Starting the Hugo server again, we will see a few changes:

Hugo with config.toml

These can be changed to your liking by altering some property in the config.toml file. This particular theme is aimed to create a portfolio website, So we can start changing the name, add a subtitle, add an image, configure the social media links, etc.

title = "<your name here>"
homeSubtitle = "<about you in subtitle>"
  name = "<your name here>"
    path     = "images/<your picture>.jpg"
    alt      = "Portrait"
    maxWidth = "150px"
    name = "email"
    url  = "mailto:<your email>"
    name = "linkedin"
    url  = "<your linkedin id>"

    name = "github"
    url  = "<your github id>"

    name = "twitter"
    url  = "<your twitter handle>"

Most of the configuration is well documented in the example site provided by the theme, I will not discuss these to keep this blog concise.

Note: To serve any static content, keep them inside the static/ directory of the site root. All contents of this static/ directory will be copied to the site root while deploying. To add the profile image, I made a directory images/ inside static/ then placed the image there. I have used a nice 🐧 emoji as the profile photo in this demo.

After applying the above settings, the site homepage looks like this:

Hugo Site Homepage

6. Add a post

To add a post, the easiest way is hugo new command:

$ hugo new posts/

The file will be generated in content/posts/. It will have some automatically generated metadata like this:

title: "First_post"
date: 2020-07-07T11:15:51+05:30
draft: true
toc: false
  - untagged

After filling it up with some lorem ipsum using the post looks like this:

Hugo New Post

7. Deployment

There are many free and paid options to host a static site like GitHub Pages, GitLab Pages, Netlify, Vercel, Firebase, Google Cloud Platform, Google Drive +, and many more. I chose Vercel as suggested by @xprilion which provides fast deployment almost without any configuration and supports many JAMStack frameworks. Vercel uses GitHub / GitLab / BitBucket as the source with automatic deployment and provides free SSL on every site. Another best feature about Vercel is that it provides this super cool domains for free.

Before the deployment, we need to define the baseURL property in config.toml file. This property should contain the final hostname of the site after deployment. Vercel by default provide https://<project_name> as domain name. For this project, it will be Use the following line:

baseURL = ["", "localhost"]

We can provide multiple hostnames as a list to make to site functional in many hosts, localhost will allow us to develop the site in our system.

To deploy the site, we need to create a GitHub Repository, I named it hugo_static_site. Now add it as a remote to our mysite local repository, track all files, commit all files, and push to master.

$ git remote add origin
$ git add .
$ git commit -am "first commit"
$ git push origin master

Now, sign up in Vercel with GitHub. From the homepage, click Import Project.

Vercel Import Project

Now choose Import Git Repository option and paste the repo URL and click Continue.

Deploying a Git Repo

Vercel should automatically detect the Framework Preset as Hugo, if it fails to do so, choose Hugo from the Framework Preset and click Deploy. You can change the project name as per your requirement. The deployment should complete within 15 seconds.

Vercel Deploy

Now the site is deployed to

Hosted Site

8. Change the domain to!

Before going further, we need to add to our baseURL property in config.toml and commit and push the change to GitHub, after that, in Vercel project page, go to Settings ➡️ Domains.

Vercel Project Settings

In the domains section, click Edit.

Vercel Domain Settings

Change the domain to and click save.

Domain Change

The final site can now be visited at

Final Thoughts

Thank you for reading this post to the end! Here, I shared my process of creating a static portfolio + blog site that may inspire you to make your static portfolio site. I would like to acknowledge Anubhav Singh who suggested me to use Vercel and it was amazing! As this is my first blog, I am eager to hear your feedback @snehangshu_!


Hugo Documentation by Hugo Authors

Hugo Theme hello-friend-ng by Djordje Atlialp