Skip to content

Deploy Hugo to Cloudflare Pages — Complete CI/CD Guide

DodaTech Updated 2026-06-22 6 min read

Deploying a Hugo site to Cloudflare Pages takes minutes — this guide walks through Git integration, build configuration, environment variables, branch previews, and custom domain setup for production deployments.

What You'll Learn

Why It Matters

Cloudflare Pages offers free hosting with global CDN distribution, automatic HTTPS, and seamless Git integration for static sites. Unlike traditional hosting, it pre-builds every commit into static assets served from 330+ edge locations worldwide, giving you sub-second TTFB without managing servers. At DodaTech, our Hugo tutorial site deploys through Cloudflare Pages, processing over 2,900 pages in under 30 seconds per build.

Real-World Use

A documentation team deploys preview builds for every pull request, allowing reviewers to see changes before merging. A marketing site uses branch-based deployments for staging and production environments. An e-commerce catalog rebuilds automatically whenever content is updated in a headless CMS webhook.

Cloudflare Pages Architecture

flowchart LR
  A[Git Repository] --> B[Cloudflare Pages]
  B --> C[Build Step]
  C --> D[Hugo Build]
  D --> E[Static Assets]
  E --> F[CDN Cache]
  F --> G[Edge Network]
  G --> H1[Visitor Tokyo]
  G --> H2[Visitor London]
  G --> H3[Visitor New York]
  style B fill:#f90,color:#fff
  style E fill:#09f,color:#fff

Prerequisites

Before deploying, ensure you have:

  • A Git repository with your Hugo site (GitHub, GitLab, or Bitbucket)
  • A Cloudflare account (free tier includes Pages)
  • Hugo installed locally for testing (hugo version)
  • A hugo.toml or config.toml with baseURL set correctly

Step-by-Step Deployment

1. Connect Your Repository

Log into the Cloudflare dashboard, navigate to Pages, and click Create a project. Connect your Git provider and select the repository containing your Hugo site.

2. Configure Build Settings

Cloudflare Pages auto-detects Hugo projects but you should verify the settings:

Setting Value
Build command hugo --gc --minify
Build output directory public
Root directory / (or your Hugo root)
Node.js version Not required for Hugo

3. Set Environment Variables

# Required environment variables in Cloudflare Pages dashboard
HUGO_VERSION = "0.128.0"
HUGO_ENV = "production"

Expected behavior: Cloudflare Pages uses the specified Hugo version to build your site. Setting HUGO_ENV=production activates production-only configurations like Google Analytics or environment-specific shortcodes.

4. Configure Hugo for Production

# hugo.toml — Production-ready configuration
baseURL = "https://tutorials.dodatech.com"
title = "DodaTech Tutorials"
enableGitInfo = true

[params]
  description = "Programming and security tutorials"
  environment = "production"

[build]
  writeStats = true

[security]
  enableInlineShortcodes = false

Expected behavior: enableGitInfo displays last-modified dates from Git history. writeStats generates a hugo_stats.json file that can be used for CSS purging with PostCSS.

5. Deploy and Verify

After the first successful deployment, Cloudflare Pages assigns a *.pages.dev domain. Verify your site loads, check the CDN cache status headers, and confirm that assets are served with proper cache headers.

Branch Previews and Staging

Cloudflare Pages creates preview deployments for every pull request:

Feature Production Preview
Branch main or master Feature branches
URL Custom domain *.pages.dev
Indexed by search Yes No
Build on push Yes Yes
Build on PR No Yes
Environment variables Production set Preview set

Configuring Preview Environment

# .cloudflare/pages.yaml — Preview configuration
preview:
  environment:
    HUGO_ENV: staging
    BASE_URL: https://staging.example.com

Expected behavior: Preview builds use HUGO_ENV=staging, which can conditionally load different analytics tokens, disable SEO indexing, and use a staging baseURL to avoid conflicting with the production site.

Custom Domain

Add a custom domain in the Cloudflare Pages dashboard under your project's Custom domains tab. Cloudflare automatically provisions an SSL certificate and manages DNS.

# DNS record (automatically managed when Cloudflare is your DNS provider)
CNAME  tutorials.dodatech.com  tutorials-dodatech.pages.dev

Common Errors

1. Build Fails with "command not found: hugo"

Cloudflare Pages requires specifying the Hugo version in an environment variable. Without HUGO_VERSION, the build environment uses a potentially outdated default. Set HUGO_VERSION = "0.128.0" in your Pages project settings.

2. Broken Assets After Deployment

Assets loading over http:// instead of https:// cause mixed content warnings. Ensure baseURL in your Hugo config starts with https://. Check that all asset references use protocol-relative URLs or absolute paths from baseURL.

3. Preview Deployments Not Building

If pull requests do not trigger preview builds, check your Pages project's Build configuration under Branch build controls. Ensure the preview branch pattern matches your naming convention (e.g., feat/* or * for all branches).

4. 404 Errors on Nested Routes

Cloudflare Pages serves static files directly. If you use clean URLs without .html, Hugo must generate index.html files in subdirectories. Configure Hugo with uglyURLs = false (default) and ensure your .htaccess or Cloudflare redirect rules handle trailing slashes.

5. Cache Returning Old Content

Cloudflare's edge cache may serve stale HTML. Invalidate the cache by navigating to Cloudflare Dashboard > Caching > Purge Cache and selecting Purge Everything. For automatic cache invalidation, configure a deploy hook that sends a purge request after each build.

Practice Questions

1. What environment variable must be set to specify the Hugo version in Cloudflare Pages?

HUGO_VERSION must be set to the desired Hugo version number (e.g., 0.128.0). Without it, Cloudflare uses a default version that may not support your site's features.

2. How do branch previews differ from production deployments?

Branch previews deploy to a *.pages.dev URL, are not indexed by search engines, and use separate environment variables. Production deployments use your custom domain and are indexed.

3. What is the purpose of enableGitInfo = true in the Hugo config?

It enables Hugo to read Git commit timestamps for each page, allowing the site to display accurate "last modified" dates without manual frontmatter updates.

4. Why might nested routes return 404 errors on Cloudflare Pages?

If Hugo is configured to generate clean URLs (default), it creates page/index.html for each route. Cloudflare Pages serves these correctly, but if the site uses uglyURLs = true, files are named page.html and clean URL requests without .html will 404.

5. Challenge: Set up a GitHub repository with two branches — main and staging. Configure Cloudflare Pages to deploy main to your custom domain and staging to a staging.pages.dev subdomain. Add a webhook that triggers a rebuild when content changes in a connected headless CMS.

Mini Project: Multi-Environment Deployment Pipeline

Build a complete deployment pipeline for a Hugo site:

  1. Create a GitHub repository with your Hugo site
  2. Connect it to Cloudflare Pages with automatic deployments
  3. Configure a staging branch with preview deployments
  4. Set up a custom domain with automatic SSL
  5. Add Cloudflare Workers for header manipulation and redirects
  6. Implement a deploy hook triggered by a GitHub Actions workflow

Start by creating the GitHub repository and pushing your Hugo site:

git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/yourusername/hugo-site.git
git push -u origin main

Then connect the repository in the Cloudflare Pages dashboard and verify that the first deployment completes successfully.

Use the Cloudflare Workers dashboard or wrangler.toml to add custom headers:

# wrangler.toml
name = "security-headers"
type = "javascript"

[headers]
  "/public/*" = { "X-Content-Type-Options" = "nosniff", "X-Frame-Options" = "DENY" }

Verify deployment success by running:

curl -I https://yourdomain.com
# Expected: HTTP/2 200 with Cloudflare headers

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro