DEV Community

Jason Hand
Jason Hand

Posted on

10 Tips for Building and Deploying Hugo Websites on Azure Static Web Apps

I have a "problem".

I buy domain names.

The guilt I feel isn’t from buying the domain so much as getting the email that GoDaddy’s auto- renewal has once again garnished my wages for a domain I haven’t even thought about in year.

I won’t share just how many domain names I own but I do know that I’m not alone in this addiction.

We’ve all come up with an amazing idea to immediately snag the TLD (top level domain) before anyone else thinks of it. The number of domains I’ve bought while still dripping wet from the shower is north of 10, easily. This year! (just kidding ... I think 🤔) What month is it again?

With a little extra free time and domains stacking up like the empty Amazon boxes in my garage, I decided to at least give each brilliant idea a landing page - a first step towards solving my domain dilemma AND the world's problems with answers to questions like

If you’re thinking to yourself -

“I wonder if he bought that domain just for this post?”

… see how the “problem” works?

I’ve been a huge fan of the static HTML generator Hugo for years. First exposed through the Devopsdays community, I have used it for literally everything. From my personal website, the podcast I co-host, and many other projects, Hugo has been my hammer of choice.

Then I found out Microsoft would be announcing Azure Static Web Apps at Build this year and I jumped at the chance to get early access.

Azure Static Web Apps

I kid you not – in less time it took Dominos to bring me my 2nd cheese pizza this week, I had live sites for MY custom domains including free SSL (Secure Sockets Layer) certificates.

Incredibly pleased with my newfound sense of productivity, I began jotting down some of the things I ran into in case others are looking to find homes for their own orphaned domain names.

📌 TL; DR - After many Hugo deployments, here are "10 Tips” I have to help you host Hugo sites on Azure Static Web Apps faster and with confidence.


Everything I’m going to show you moving forward assumes the following:

  • ✅ You have an Azure account (sign up for free)
  • ✅ You have a Hugo site stored in a GitHub repo you own

Already have an Azure account? -- 🔗 Deploy from secret link

Static Web App Preview
Once you’ve entered the basic information and moved on to the initial build settings you will find three fields to review in the initial workflow file: App location, Api location, and App artifact location.

Build Parameters

📌Tip #1 -The Initial Deployment May Fail

The correct settings for your Hugo site depend on many factors, so don’t be surprised if the first build fails. Some themes require specific conditions to be met to build correctly.

During your first deployment, a file named azure-static-web-apps-xxxx.yml containing information for a GitHub Action will be created and added to the master branch of your Hugo repo. After synchronizing your repo with your local machine, you can edit the file.

With only 50-ish lines, it’s not too scary. However, it took me a few attempts to spot an improper indention in the file that definitely “mattered.”

It Mattered

Don’t get discouraged if you find a big red X next to your first GitHub Action.

Failed Build

For example, the Academic-Kickstart theme I use for “On-call Life" requires Hugo to build the site with the “extended” flag as shown below.

    - uses: actions/checkout@v2
        submodules: true

    - name: Setup Hugo
      uses: peaceiris/actions-hugo@v2.4.8
        hugo-version: "latest"
        extended: true

    - name: Build
      run: hugo
      extended: true
Enter fullscreen mode Exit fullscreen mode

📌Tip #2 - App Location Should Be Set to Public (but not always)

This is where your static files will be stored and served behind the scenes. In most cases, public should be correct but not always.

Some themes require specific entries in the config.toml file that may be different from a super simple Hugo site like the one in the online tutorial on Docs.

The Slate theme I used for “Jhand.TV” publishes and serves the HTML content out of the docs directory by default (rather than public).

Not Public Directory

To get my site to build, I updated the app_location entry in my workflow file to the following and everything was smooth sailing from there.

        app_location: 'docs' # App source code path
        api_location: '' # Api source code path - optional
        app_artifact_location: '' # Built app content directory - optional
Enter fullscreen mode Exit fullscreen mode

📌 Tip #3 - Api Location Should Be Empty

Hugo sites rarely include a directory named api by default.

If you notice a warning in GitHub Actions complaining about a missing api location, it’s probably because you left the default text in the parameter field during the initial deployment. Unless you have a directory in the root of your repo named api, you can leave this empty.

Although you can force GitHub Actions to ignore the api directory by removing it from the yaml workflow file, if you create a directory named api with a file it won’t generate an warning message during the build step.

📌 Tip #4 - App Artifact Should Be Empty

This one can be a little confusing. For most static web apps, an “artifact” is created during the build process which is then deployed.

In the world of Hugo, our only “artifact” is the collection of html, CSS, and JavaScript files that were outputted to the public folder I mentioned in Tip #2. However, that is not what this field is asking for.

If you happen to put public in by mistake or just because you like to poke at things and understand what happens (like me), it will complain in the GitHub Action logs if you don’t have a public folder. Just like in Tip #3 with the api folder, you can silence the error by pointing to an empty public folder.

📌 Tip #5 - Leave Your Public Folder (inside Hugo) Out of This

Anyone who has worked with Hugo knows that when you build the site locally, all HTML, CSS, and miscellaneous files are placed into a directory within the Hugo directory synchronized with your Hugo repository on GitHub. Usually the directory is public, but as mentioned in tip #3, not always.

This means that if the public directory exists locally when you push your files, you will be transmitting everything in the public folder (or similar) even though it is not needed.

GitHub Actions is going to rebuild the site each time there is a change to the branch. Because of this, it’s best to either remove any public folders in your Hugo directory OR put it in your .gitignore file.

📌 Tip #6 - There Can Be Only One Workflow

Be sure to remove any old yaml files created that may still be loitering in your .github\workflows directory from earlier deployment attempts from earlier deployment attempts.

Although they technically won’t cause a problem with the deployment of your current site, GitHub Actions will still attempt to run the old CI/CD workflow. Because the yaml file references old resources that likely no longer exist, errors will occur, and the build associated with the previous workflow will fail.

📌 Tip #7 - Mind Your Size

There is a 100Mb size restriction for deployments.

When trying to deploy I had many of my images in the repo on GitHub. Even though none of them were exceptionally large and my image directory rarely changed, when Hugo built the new site it used the images stored inside my Hugo directory which collectively exceeded the 100Mb limit.

Here is the error message I get when Azure Static Pages tries to build.

Too Big

Once I moved all my images into blob storage on Azure and pointed the markdown files to those public links instead of assets inside my Hugo repository, the overall size of my build fell far below the limitations to build and deploy perfectly.

📌 Tip #8 - Submodules

Many themes require a reference to their original repository to properly build all the files for your site. If the theme you are using includes a step of git submodule, you are in this situation.

The default workflow file takes submodules into consideration but in some cases, you may need to create a .gitmodules file in your repository.

[submodule "themes/hugo-elate-theme"]
    path = themes/hugo-elate-theme
    url =
Enter fullscreen mode Exit fullscreen mode

📌 Tip #9 - Just HTML

What if you just want to deploy HTML?

Regardless of how the site was built, if it doesn’t require any server-side processing, you can still take advantage of Azure Static Web Apps.

Assuming the root directory of the GitHub repository is the root of the site, use the following in your yaml workflow file to skip the build process and deploy the files as a ready-to-go static site.

        app_location: '/' # App source code path
        api_location: '' # Api source code path - optional
        app_artifact_location: '/' # Built app content directory - optional
Enter fullscreen mode Exit fullscreen mode

This is exactly what I did with and

They are both simple HTML sites with an index.html, basic CSS, and some JavaScript.

📌 Tip #10 - Learn More and Experiment

Azure Static Web Apps is a new Azure service for deploying and hosting static web applications and sites built with Hugo, Gatsby, Jekyll, and many others. With my tips above I hope you too can find a home for all the amazing domain ideas you came up with.

I've had a blast playing around with this new tool. Having the ability to deploy and host my Hugo sites just by pushing code to my GitHub repo AND have it point to my own custom domain with SSL is a game changer for me. I suspect it might be for you!

I can't wait for you try it out yourself. Experiment and let me know what you think.


Check out some of the documentation, tutorials, and resources currently available at the release of Azure Static Web Apps in Preview.

Hugo Sites I moved to Azure Static Web apps

Top comments (8)

mattstratton profile image
Matty Stratton

Great tips! I feel like adding "public" to your .gitignore is a good tip for all Hugo users/repos, whether they use Azure Static Web Apps or not :)

Another tip that might be helpful is that some themes are picky about what version of Hugo they support, so floating on "latest" can be iffy - maybe add something about how you can specify the specific Hugo version for the peaceiris/actions-hugo Action? I know you show that part of the code when you show how to use "extended", but a lot of time folks can get burned on Hugo versions when themes haven't been updated to support latest, etc (or even their own theme, not that this has ever happened to me...)

jasonhand profile image
Jason Hand

Excellent points!

hugo-version: "latest" might not be what your Hugo theme needs.

buhakmeh profile image
Khalid Abuhakmeh
"Once I moved all my images into blob storage on Azure and pointed the markdown files to those public links instead of assets inside my Hugo repository"

How did you do this step?

  • Was it part of tweaking the GitHub action?
  • Was it manually?
jasonhand profile image
Jason Hand

It was a manual step since I only needed to do it once. I have a blob storage container in a storage account where I uploaded everything via the Storage Explorer in the Azure portal. Took a couple of seconds but I don't have many images.

paulweisjr profile image
Paul Weis

How can I wrap Azure AD authentication around my Azure static app (similar to how I do for an app service)? I want to limit accessibility to my site to just my Azure AD users.

charles66982918 profile image
charles hollins

Very good read. Thanks

Some comments may only be visible to logged-in visitors. Sign in to view all comments.