31.5 Firebase Hosting: Hugo on Google's CDN
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 servesindex.htmlfiles 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
- The Build Step: You must remember to run
hugobefore everyfirebase 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. - 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_headersfile like Netlify does. You have to configure it all in thehostingsection of the JSON. - 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 hostingwith the-Vflag (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!"