Hugo is a popular open-source Static Site Generator (SSG) designed to help developers build and manage websites quickly and efficiently. It can be used to create blogs, portfolios, and all forms of personal websites that do not require dynamic data.

When you build sites with Hugo, you’d definitely want to host them online so you can share them with all those who need to access them. This is where Kinsta’s Static Site Hosting comes in!

Understanding Kinsta Static Site Hosting

Kinsta Static Site Hosting is a free service dedicated to hosting static sites. It does this by serving pre-built HTML, CSS, and JavaScript files that don’t change dynamically. It works by connecting a repository hosted on a Git provider (BitBucket, GitHub, or GitLab) to your Kinsta account and deploying your static site files to the internet.

Kinsta’s Static Site Hosting can automatically build sites from SSGs built on top of Node.js, while for others like Hugo, written in Go programming language (Golang), you’d need to devise another approach.

This article explains how to host your Hugo site to Kinsta for free with Kinsta’s Static Site Hosting!

Deploy Your Hugo Site to Kinsta Static Site Hosting

There are three ways to deploy your Hugo site to Kinsta Static Site Hosting:

  1. Build your website using Continuous Integration and Continuous Deployment (CI/CD) and then deploy it.
  2. Utilize the hugo-bin developer dependency.
  3. Serve locally built static files.

In this article, we go through all of them.

Prerequisites

To follow along with this tutorial, we assume you have:

  • Experience with Hugo and Git.
  • A Hugo site running locally.

Build Your Site With CircleCI and Deploy to Kinsta

For the first method, let us use CircleCI as the CI/CD tool. This method involves creating a CircleCI workflow that builds your Hugo site into a new branch named deploy and then configuring Kinsta to deploy the static files from this branch.

Advantages of Using CI/CD

With this method, you can avoid the need to locally build your site before pushing it to your Git repository. Normally, Kinsta handles the site-building process for SSGs that are based on Node.js, but for other SSGs like Hugo, using a workflow can help handle the site-building process automatically.

Additionally, you can add other jobs to your CI/CD configuration file, for example, to lint and test your code. You also guarantee that your deployment is only updated if the CI/CD pipeline is completed successfully.

Step 1: Create the Configuration File

Begin by creating a .circleci folder in your Hugo project’s root directory. Inside this folder, create a config.yml file to define your workflow’s configuration.

Step 2: Push Your Code to a Git repository

Create a Git repository using your preferred Git provider and push your code to the repository.

Step 3: Create an Orphan Branch

Next, create an empty orphan branch called deploy, where the static files for deployment will be pushed. Execute the following commands in your project’s terminal:

git switch --orphan deploy
git commit --allow-empty -m "Initial commit on deploy branch"
git push -u origin deploy

Do not add any files to this branch; it will be automatically populated by the CircleCI workflow with the contents of Hugo’s generated public folder.

Step 4: Create a CircleCI Account

Visit the CircleCI website and create an account if you don’t already have one. You can sign up using your preferred Git provider, which makes it easier to access your repositories without further configuration.

Step 5: Configure Your Repository

After logging in, go to your CircleCI dashboard, click Projects on the left sidebar, and select the repository you want to configure. CircleCI will automatically detect your configuration file.

Configure your repository with CircleCI
Configure your repository with CircleCI.

Click the Set Up Project button to grant CircleCI access to your codebase and execute workflows upon code changes.

Step 6: Define CircleCI Configuration

You now have a CircleCI configuration file created. Let’s build its content. Ensure you’re in your default branch (not in the deploy branch) and start by defining the CircleCI version, which currently is 2.1:

version: 2.1

Step 7: Define Executors

Since this is a Hugo project, you’d need to define an executor to run the jobs. Define the hugo-executor here so you don’t have to define it for every job. This executor uses a Docker image (cibuilds/hugo:latest) to create a consistent environment for building the Hugo site:

executors:
  hugo-executor:
    docker:
      - image: cibuilds/hugo:latest

Step 8: Define Jobs

Next, define two jobs: build and push build. These jobs specify the steps to be executed in each job:

jobs:
  build:
    executor: hugo-executor

  push build:
    executor: hugo-executor

Build Job:

This job is responsible for building your Hugo site and storing the static files generated in the workspace temporarily so they can be accessible for later use in the push build job.

build:
  executor: hugo-executor
  steps:
    - checkout

    - run:
        name: Update theme
        command: git submodule update --init --recursive

    - run:
        name: Build Hugo site
        command: hugo --destination=workspace/public

    # Persist the 'build' directory to the workspace
    - persist_to_workspace:
        root: workspace
        paths:
          - public

The job above specifies that it uses the hugo-executor executor defined earlier. And then runs four major steps:

  • checkout: This step checks out your project’s source code from the GitHub repository.
  • Update theme: This step initializes and updates Git submodules (if any) to ensure that your Hugo theme is up-to-date. This is useful if your Hugo site uses Gitmodules to reference the theme used instead of pushing large files of themes already available on GitHub.
  • Build Hugo site: This step builds the Hugo site and specifies the destination folder as workspace/public.
  • persist_to_workspace: This step persists the public directory (output of the Hugo build) to the workspace for later use in the push build job.

Push Build Job:

The push build job is responsible for pushing the built site to an orphan branch (deploy) in your GitHub repository. This way, your code remains on the default branch, and the deploy branch hosts only your site’s static files.

push build:
  executor: hugo-executor
  steps:
    - attach_workspace:
        at: workspace

    - run:
        name: Push build folder to GitHub
        command: |
          # Configure Git identity (replace <GitHubUsername> with your actual username)
          git config --global user.name "<GitHubUsername>"
          git config --global user.email "<GitHubUsername>@users.noreply.github.com"

          # Clone the repository (replace <your-repo-name> with your actual repository URL)
          git clone --branch deploy --depth 1 https://<GitHubUsername>:${GITHUB_TOKEN}@github.com/<GitHubUsername>/<your-repo-name>.git deployment

          # Copy the 'public' directory to the deployment folder
          cp -R workspace/public deployment

          # Navigate to the deployment folder
          cd deployment

          # Commit and push changes
          git add .
          git commit -m "Auto generated from ${CIRCLE_SHA1}"
          git push

The job above does the following:

  • attach_workspace: This step attaches the workspace where the build job persisted the public directory.
  • Push build folder to GitHub: This step performs several Git operations:
    • Configures Git identity with your GitHub username and email.
    • Clones your GitHub repository into a folder named deployment on the CircleCI runner machine.
    • Copies the contents of the workspace/public directory (the built Hugo site) into the deployment folder.
    • Changes the working directory to deployment.
    • Commits the changes with a message indicating it’s an auto-generated commit from CircleCI.
    • Pushes the changes to a new branch on your GitHub repository.

Make sure to replace <GitHubUsername> and <your-repo-name> with your actual GitHub username and repository name. Also, ensure you create a GitHub access token so that CircleCI can access your GitHub account.

Define scopes for GitHub access token
Define scopes for GitHub access token.

Then, add the token as an environment variable named GITHUB_TOKEN in your CircleCI Project Settings.

Step 9: Define Workflow

With your jobs set up, the next phase involves configuring your workflow. Continuing your CircleCI configuration, create a workflow that triggers the build job when there are code changes on the main branch and requires the build job to complete successfully before running the push build job:

workflows:
  version: 2
  build-and-deploy:
    jobs:
      - build:
          filters:
            branches:
              only:
                - main
      - push build:
          requires:
            - build

Step 10: Commit and Push

Once your workflow is successfully configured, commit and push your changes to your Git repository. CircleCI automatically detects the presence of the configuration file and triggers your defined workflows upon code changes.

Details of CircleCI pipeline
Details of CircleCI pipeline.

When you check your GitHub repository, the deploy branch already has the public folder, which contains the static files.

You can crosscheck the complete CircleCI configuration in this sample repository.

Step 11: Deploy Static Files to Kinsta

Deployment to Kinsta happens in just seconds, especially now that the static files are already built. Follow these steps to deploy your Hugo site for free with Static Site Hosting:

  1. Log in or create an account to view your MyKinsta dashboard.
  2. Authorize Kinsta with your Git provider.
  3. Click Static Sites on the left sidebar, then click Add site.
  4. Select the repository and the branch you wish to deploy from (the deploy branch).
  5. Assign a unique name to your site and click Continue.
  6. Leave the Build command and Node version fields empty and specify the Publish directory as public.
  7. Finally, click Create site.

And that’s it! You now have a deployed site within a few seconds. A link is provided to access the deployed version of your site. You can later add your custom domain and SSL certificate if you wish.

Using Hugo-Bin to Build and Deploy Your Hugo Site to Kinsta

The Hugo-bin package is a binary wrapper for Hugo. It makes it possible for you to build and serve your Hugo project with Node.js commands. This method doesn’t need a CI/CD tool to build your site before deploying it to Kinsta Static Site Hosting.

To use the Hugo-bin package in your Hugo project:

  1. Initialize Node.js in the root of your project by running the npm init -y command.
  2. Next, install Hugo-bin as a developer dependency in your project by running this command:
npm i -D hugo-bin
  1. Add the following script commands to your package.json file:
"scripts": {
    "build": "hugo",
    "create": "hugo new",
    "serve": "hugo server"
  }

With this, Kinsta would be able to build and serve your Hugo site without you needing to build your files before deploying.

Once all is done, push your code to your Git repository. Follow these steps to deploy your static site to Kinsta:

  1. Log in or create an account to view your MyKinsta dashboard.
  2. Authorize Kinsta with your Git provider.
  3. Click Static Sites on the left sidebar, then click Add site.
  4. Select the repository and the branch you wish to deploy from.
  5. Assign a unique name to your site.
  6. Add the build settings in the following format:
    • Build command: npm run build
    • Node version: 18.16.0
    • Publish directory: public
  1. Finally, click Create site.

And that’s it! You now have a deployed site within a few seconds.

Serving Your Static Files Only to Kinsta

Finally, another method for deploying your Hugo site to Kinsta involves building your site locally and then deploying it to Kinsta. This process generates a public folder at the root of your project. However, the main disadvantage of using this method is that you have to build your site locally before every push, which can be time-consuming and less convenient compared to other methods that automate the site-building process.

By default, the public folder is excluded from your Git repository due to its inclusion in your .gitignore file. To include it in your repository and deploy your site to Kinsta:

  1. Remove the public folder from your .gitignore file.
  2. Follow the deployment steps explained above.
  3. Deploy the repository to Kinsta, ensuring that the Build command and Node version fields remain empty, as your site is already built.
  4. Specify the Publish directory as public.

Alternatively, you can choose to push only the static files to your GitHub repository. For this approach, there’s no need to initialize a Git repository in the root folder of your project. You only need to run git init within the public folder. This allows you to keep the version control for your static files separate from the rest of your project.

In this scenario, when pushing the files separately without placing them within a public folder, specify the Publish directory as . when deploying to Kinsta. This notation represents the root folder, and Kinsta will serve the files accordingly.

Summary

This article has explained three effective methods for deploying your Hugo site for free on Kinsta’s Static Site Hosting platform. You have the flexibility to choose the method that aligns best with your specific requirements. Additionally, for in-depth insights on creating a lightning-fast static site using Hugo, read our comprehensive guide.

Joel Olawanle Kinsta

Joel is a Frontend developer working at Kinsta as a Technical Editor. He is a passionate teacher with love for open source and has written over 200 technical articles majorly around JavaScript and it's frameworks.