Right, Firebase Hosting. It’s Google’s CDN with a developer-friendly face, and honestly, it’s a fantastic choice for a Hugo site. It’s not quite as dead-simple as Netlify, but it gives you a terrifyingly fast global cache, free SSL, and the sheer might of Google’s infrastructure without having to utter the words “Google Cloud Platform.” Think of it as GCP’s polite, well-dressed cousin who actually shows up to your party on time.

The magic here is that Hugo and Firebase Hosting speak the same language: static files. We’ll build the site locally (or in a CI pipeline) and then hand the resulting public/ directory to the firebase CLI tool, which efficiently uploads it to be served from a global CDN. It’s a beautiful, simple handoff.

Getting the Tools: The Firebase CLI

First, you need the Firebase CLI. Don’t just sudo apt-get install some ancient package; you want the Node.js version. It’s the officially maintained one and gets all the shiny new updates first.

npm install -g firebase-tools

Next, log in. This will kick open a browser tab to authenticate you with your Google account. It’s a much nicer experience than dealing with service account keys for a simple deploy.

firebase login

Initializing Your Project

Now, navigate to your Hugo site’s root directory (where your config.toml and content/ folder live). Here’s where we tell Firebase what we’re about. Run:

firebase init

You’ll get a snazzy CLI interface. Use your arrow keys to select Hosting, hit space to mark it, and then enter. Now, the important bits:

  • “Select a default Firebase project”: You can either associate this with an existing Firebase project you’ve created in the Firebase console or create a new one right here. I usually create the project in the web console first because I like to set up my custom domain there, but doing it here works fine too.
  • “What do you want to use as your public directory?”: This is crucial. Type public. This is Hugo’s default output directory, and it’s where Firebase will look for the files to upload.
  • “Configure as a single-page app (rewrite all urls to /index.html)?”: Say no. Hugo generates a proper static site with actual HTML files for each page (e.g., about/index.html). We don’t need the SPA rewrite. Firebase will handle the clean URLs for us automatically because of how it serves index.html files from directory paths.
  • “Set up automatic builds and deploys with GitHub?”: This is optional. It’s neat, but for now, let’s keep it simple and say no. We can always set up a GitHub Actions workflow later.

This command creates two files: firebase.json (your hosting configuration) and .firebaserc (which holds your project reference).

The firebase.json File: Your Rulebook

Your firebase.json is where the configuration lives. For a standard Hugo site, it should look something like this. The cleanUrls and trailingSlash settings are key to making Hugo’s output play perfectly with Firebase’s servers.

{
  "hosting": {
    "public": "public",
    "cleanUrls": true,
    "trailingSlash": false,
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ]
  }
}

The cleanUrls setting means yourproject.web.app/about.html will be served as yourproject.web.app/about. The trailingSlash set to false means it won’t force a trailing slash, which is Hugo’s default behavior and generally what you want. The ignore array is smart; it stops the CLI from wasting time uploading things like your node_modules or hidden files.

Building and Deploying: The Moment of Truth

You don’t deploy your Hugo source; you deploy the rendered output. So the workflow is always a two-step dance:

hugo # This builds your site into the /public directory
firebase deploy # This uploads the contents of /public

That’s it. The CLI will churn for a moment, give you a deploy complete message, and spit out a URL (usually https://<your-project-id>.web.app). Your site is now live on Google’s CDN. It feels a bit more manual than Netlify’s git-based magic, but you have explicit control over when the build happens.

The Gotchas: Where They Get You

  1. The Build Step: You must remember to run hugo before every firebase deploy. Forget, and you’re deploying an old version of your site. This is the biggest pitfall. The solution? Automate it. A simple shell script (./deploy.sh) that runs both commands saves your sanity.
  2. Redirects and Headers: Need to set a custom header for your security policy or redirect a old URL? You do that in firebase.json, not in Hugo. The Firebase CLI doesn’t parse your _headers file like Netlify does. You have to configure it all in the hosting section of the JSON.
  3. The Cache Is King (and a Tyrant): Firebase’s CDN is aggressively fast because it’s aggressively cached. Sometimes, after a deploy, you’ll still see the old version. You need to run firebase deploy --only hosting with the -V flag (for debug info) and wait a minute for the global cache to invalidate. It’s usually quick, but it’s not instantaneous.

For a rock-solid deployment script that handles the build and deploy together, create a simple shell file:

#!/bin/bash

echo "Building site with Hugo..."
hugo --minify # --minify is optional but a good practice

echo "Deploying to Firebase..."
firebase deploy --only hosting

echo "Deploy complete!"