BetterLink Logo BetterLink Blog
Switch Language
Toggle Theme

Complete Guide to Deploying Static Blogs on Cloudflare Pages: No More Config Mistakes for 5 Major Frameworks

Cloudflare Pages deployment dashboard displaying static site generators

It’s 2 AM. You’ve just finished writing your blog’s first post and click the “Deploy” button with excitement. Three minutes later, Cloudflare Pages shows “Deployment successful.” You eagerly copy the link to your browser, and… blank page. Press F12 to open the console—404 errors everywhere.

To be honest, I went through the same crushing feeling when I first deployed my Astro blog. I Googled “Cloudflare Pages deployment failed” and found answers all over the map: some said it was the build command, others said the output directory was wrong, and some suggested modifying config files. I tried for three or four hours, changed several configs, nothing worked. Finally, I discovered it was a simple mistake: the output directory was set to public, while Astro’s default is dist.

Later, I helped friends deploy Hugo and Hexo blogs and realized 90% of deployment failures come from not understanding two configs: build command and output directory. Each framework has different defaults, and if you blindly copy someone else’s tutorial, you’ll likely fall into a trap.

This article will show you the exact configs for the 5 most popular static blog frameworks (Astro, Hugo, Hexo, Gatsby, Eleventy) on Cloudflare Pages, and teach you how to quickly troubleshoot “blank page” and “build failed” issues. Follow along, and you’ll be online in 10 minutes from Git repo to production.

Why Choose Cloudflare Pages? (But Note the 2025 Platform Changes)

Let me explain why I recommend Cloudflare Pages for deploying static blogs.

Free, and genuinely fast. Cloudflare has over 300 data centers globally. Your blog gets automatically distributed to these nodes, so readers get fast access wherever they are. I’ve used GitHub Pages and Vercel before—Cloudflare Pages is definitely more stable speed-wise, especially for Chinese visitors. And it’s completely free with no traffic limits or build count restrictions.

Git auto-deployment is hassle-free. Just connect your GitHub or GitLab repository, then every git push triggers automatic build and deployment by Cloudflare. It also generates preview links for every Pull Request, letting you check effects before merging. This is especially useful for team collaboration.

Free SSL certificates and custom domains included. No need to wrestle with certificate configs. Binding your own domain is simple, with DNS resolution taking just minutes.

However, I need to tell you upfront: Cloudflare adjusted its platform strategy in April 2025, officially pushing Cloudflare Workers. The Pages platform has basically entered “maintenance mode” with no major feature updates planned.

That said, for deploying static blogs, this change doesn’t really affect us. Pages remains stable and fully functional. If you just want to set up a blog or documentation site without complex server-side rendering or edge computing, Pages is still the best choice. Workers is better suited for projects requiring dynamic features, API routes, or advanced edge computing.

Bottom line: if you’re deploying a pure static blog now, go ahead and use Pages. If you need server-side features later, you can always migrate to Workers.

Standard Configs for 5 Major Frameworks (Core Section)

Alright, here’s the important part. This is my compiled list of exact configs for the 5 major static blog frameworks—just copy and use them.

Quick Config Table

FrameworkBuild CommandOutput DirectoryImportant Notes
Astronpm run builddistDefault works, SSR needs extra config
HugohugopublicMust set HUGO_VERSION environment variable!
Hexohexo generatepublicSome themes need NODE_VERSION
Gatsbygatsby buildpublicSimplest, rarely errors
Eleventynpx @11ty/eleventy_siteNote the underscore prefix
Next.jsnpx opennextjs-cloudflare.worker-next2025 new method, ignore old tutorials

Quick note: bookmark this table—I’ve personally verified each config. Below, I’ll explain what to watch out for with each framework.

Astro Config

Astro is my current favorite static blog framework. Great performance and pleasant to write with.

Standard config:

  • Build command: npm run build or direct astro build
  • Output directory: dist

If you’re using a pure static site (SSG), just use the default config. But there’s a catch: if you want server-side rendering (SSR), you need to install the @astrojs/cloudflare adapter first, then add this to astro.config.mjs:

import cloudflare from '@astrojs/cloudflare';

export default {
  output: 'server',
  adapter: cloudflare()
};

Also, if you want to customize the output directory (like changing to build), you can set it in the config file:

export default {
  outDir: 'build'
};

But I suggest not changing it. Use the default dist to avoid confusing collaborators later.

Hugo Config (Most Error-Prone)

Hugo has the most gotchas. When I first deployed a Hugo blog, I spent a whole night figuring it out.

Standard config:

  • Build command: hugo or hugo -b $CF_PAGES_URL
  • Output directory: public
  • Environment variable (required): HUGO_VERSION = 0.143.1 (or your needed version)

Here’s the key: Cloudflare Pages defaults to Hugo version 0.54, from 2019! Most Hugo themes now require 0.80+, even 0.120+. If you don’t manually set HUGO_VERSION, deployment will definitely fail.

How to set environment variables? I’ll explain in detail in the “Hands-On Deployment” section, but remember this now: In Cloudflare Pages project settings, go to Settings > Environment variables and add:

  • Variable name: HUGO_VERSION
  • Value: 0.143.1 (must be precise version, like 0.143.1, not 0.143)

One more detail: Hugo’s baseURL config. If you’re using Cloudflare’s .pages.dev domain (not your own), the build command should be:

hugo -b $CF_PAGES_URL

$CF_PAGES_URL is automatically provided by Cloudflare and sets the correct domain based on deployment environment. This way your internal links, RSS, sitemap, etc. all work properly.

Hexo Config

Hexo is a veteran static blog framework with relatively simple config.

Standard config:

  • Build command: hexo generate (shorthand hexo g also works)
  • Output directory: public

Hexo rarely has major issues, but some themes or plugins require specific Node.js versions. If build fails, try setting the NODE_VERSION environment variable:

  • Variable name: NODE_VERSION
  • Value: 14.3 or 18.17.0 (check your project’s version)

Run node -v locally to see your version, then set Cloudflare Pages to match.

Gatsby Config

Gatsby is the most worry-free, rarely errors.

Standard config:

  • Build command: gatsby build
  • Output directory: public

That simple. No extra config needed, just fill it in. I’ve helped friends deploy several Gatsby blogs—never had a problem.

Eleventy Config

Eleventy (11ty) is a lightweight static site generator with simple config too.

Standard config:

  • Build command: npx @11ty/eleventy
  • Output directory: _site (note the underscore prefix)

One thing to note: the output directory is _site with a leading underscore. Don’t accidentally type site or it won’t find the files.

If you want to customize the output directory, create a .eleventy.js file in your project root and add:

module.exports = function(eleventyConfig) {
  return {
    dir: {
      output: "public"
    }
  };
};

Next.js Config (2025 Changes)

If you’re using Next.js for your blog, note an important 2025 change.

Standard config (2025 new method):

  • Build command: npx opennextjs-cloudflare
  • Output directory: .worker-next

Important: The old @cloudflare/next-on-pages package used in many tutorials is deprecated. Don’t use it anymore. Cloudflare now recommends the new @opennextjs/cloudflare adapter.

If you see old tutorials still mentioning next-on-pages, skip them—they’re outdated. New method setup:

  1. Install dependency: npm install @opennextjs/cloudflare
  2. Build command: npx opennextjs-cloudflare
  3. Output directory: .worker-next

But honestly, if you just want a static blog, I don’t really recommend Next.js. It’s better suited for apps needing dynamic features. For pure static content, Astro or Hugo will be lighter and faster.

Hands-On: Complete Flow from Git Repo to Online (Step-by-Step Tutorial)

Alright, now that you know the configs, let me walk you through deployment from scratch. The whole process takes about 10 minutes.

Preparation

Before starting, confirm these three things:

  1. Code is pushed to GitHub or GitLab - Open your repository page and confirm latest code is there
  2. Project has package.json (if Node.js project) - Make sure dependencies are listed, not just installed locally without being in package.json
  3. Check .gitignore - Confirm node_modules, dist, public, etc. directories are in .gitignore; don’t push build artifacts

I once met a friend who pushed node_modules to Git too, causing all kinds of deployment conflicts. Check .gitignore to avoid problems.

Detailed Deployment Steps

Step 1: Log into Cloudflare, enter Pages

Open dash.cloudflare.com, log in to your account (register one first if you don’t have it—it’s free).

Find Workers & Pages in the left menu, click in, then click the Create application button in the upper right.

Step 2: Select “Connect to Git”

You’ll see two options:

  • Connect to Git - Auto-deploy from GitHub/GitLab (we’ll choose this)
  • Direct Upload - Manual file upload (not recommended, requires manual transfer every time)

Select Connect to Git, then choose GitHub or GitLab.

Step 3: Authorize Access

First-time connection requires authorizing Cloudflare to access your Git repository. Click the Sign in button to jump to GitHub/GitLab’s authorization page.

Permission note: If you don’t want to give Cloudflare access to all repositories, select “Only select repositories” to authorize specific ones only.

Authorization complete jumps back to Cloudflare page.

Step 4: Select Repository to Deploy

Find your blog project in the repository list and click it.

If you don’t see your repository, click the refresh button in the upper right or go back to the previous step to re-authorize.

Step 5: Configure Build Settings (Critical!)

Now for the most important config step—don’t fill it wrong.

  • Project name: Project name, becomes part of your .pages.dev domain. For example, enter my-blog and your domain will be my-blog.pages.dev.
  • Production branch: Production branch, usually main or master.
  • Framework preset: Framework preset, you can select your framework here (Astro, Hugo, etc.) or select None.

Here’s the key: Build settings

Fill in accurate config here based on your framework, following the config table above:

  • Build command: Build command

    • Astro: npm run build
    • Hugo: hugo or hugo -b $CF_PAGES_URL
    • Hexo: hexo generate
    • Gatsby: gatsby build
    • Eleventy: npx @11ty/eleventy
    • Next.js: npx opennextjs-cloudflare
  • Build output directory: Output directory

    • Astro: dist
    • Hugo: public
    • Hexo: public
    • Gatsby: public
    • Eleventy: _site
    • Next.js: .worker-next

If you selected Framework preset, Cloudflare will auto-fill some defaults, but they may not be correct. Double-check manually.

Step 6: Set Environment Variables (If Needed)

Scroll down and find Environment variables (advanced), click Add variable.

Add necessary environment variables based on your framework:

  • Hugo projects must add:

    • Variable name: HUGO_VERSION
    • Value: 0.143.1 (or your needed version, must be three digits precise)
  • Hexo projects (if needed):

    • Variable name: NODE_VERSION
    • Value: 14.3 or 18.17.0 (based on your local version)

After filling environment variables, config is complete.

Step 7: Save and Deploy

Double-check the config, then click Save and Deploy at the bottom of the page.

Cloudflare will start building your project. You’ll see a build log page showing real-time progress. Usually completes in 1-3 minutes.

Step 8: View Deployment Result

After successful build, page shows “Success! Your site is live!” with a link below in the format your-project-name.pages.dev.

Click the link. If everything’s normal, you’ll see your blog!

Detailed Environment Variable Setup

You could set environment variables during deployment, but if you didn’t or need to modify them, do this:

  1. Enter your Cloudflare Pages project
  2. Click the Settings tab at top
  3. Select Environment variables in left menu
  4. Click Add variable button
  5. Fill in variable name and value, click Save

Common environment variables:

  • HUGO_VERSION: Hugo version number (like 0.143.1)
  • NODE_VERSION: Node.js version number (like 18.17.0)
  • CF_PAGES_URL: Cloudflare provides automatically, no manual setup needed, used for baseURL

Important reminder: After modifying environment variables, you need to redeploy for them to take effect. Go to Deployments tab, find the latest deployment, click the three dots on the right, select Retry deployment.

Preview Deployments

There’s a super useful feature I must mention: every time you create a Pull Request, Cloudflare automatically generates a preview link.

For example, if you create a PR on GitHub to merge a new article, Cloudflare will auto-build that PR’s code and generate an independent preview address. You can check the effect first before merging to main branch.

This is especially useful for team collaboration, letting multiple blog writers review each other’s content.

What to Do When Problems Arise? Common Errors and Troubleshooting

You’ll inevitably encounter problems during deployment. Don’t panic. Here I’ve summarized the three most common errors and troubleshooting methods, covering about 95% of cases.

Problem 1: Build Failed

Error appearance: Deployment stuck on “Building” state, then shows “Build failed” after a while with a red error icon.

This is the problem I’ve encountered most. First, don’t rush to redeploy—check the error log.

Troubleshooting steps:

  1. View build log

    • On the failed deployment page, click View build log or Deployment details
    • Scroll to the bottom for red error messages
    • Focus on the last few lines, they usually tell you what went wrong
  2. Check if build command is correct

    • Go back to Settings > Build & deployments
    • See if Build command matches the config table above
    • Common mistake: typing npm build instead of npm run build (missing run)
  3. Check if dependencies are complete

    • If error log says “Cannot find module” or “Command not found”
    • Missing dependency, check if package.json has that package
    • Might have installed locally but forgot to add to package.json (using npm install --save automatically adds it)
  4. Confirm framework version

    • Hugo projects: 99% of build failures are from not setting HUGO_VERSION
      • Error log might say “Theme requires Hugo Extended version”
      • Go to Settings > Environment variables and add HUGO_VERSION = 0.143.1
    • Hexo projects: Might be Node.js version mismatch
      • Set NODE_VERSION = 18.17.0 (or your local version)

Real example: When I helped a friend deploy a Hugo blog, the build log showed “Hugo version 0.54.0 does not support this theme.” Checked it—version too old indeed. Added HUGO_VERSION = 0.120.0 environment variable, redeployed, instant success.

Problem 2: Blank Page (Most Common)

Error appearance: Deployment successful, but visiting website only shows blank page. F12 opens console with tons of 404 errors.

I’ve encountered this problem way too many times. 90% caused by wrong output directory.

Troubleshooting steps:

  1. Open browser developer tools (F12)

    • Switch to Console tab, check for errors
    • Switch to Network tab, refresh page, see which resources are 404
    • Switch to Sources tab, check if file structure is correct
  2. Check output directory config

    • This is the most common cause, accounting for 90%
    • Go back to Cloudflare Pages Settings > Build & deployments
    • Check if Build output directory is correct
    • Common mistakes:
      • Astro project filled public instead of dist
      • Hugo project filled dist instead of public
      • Eleventy project filled site instead of _site (missing underscore)
  3. Check baseURL or publicPath config

    • If deploying to subpath (like example.com/blog), might need to configure baseURL
    • Hugo projects: Change build command to hugo -b $CF_PAGES_URL
    • Astro projects: Set base: '/blog' in astro.config.mjs
    • Vue/React projects: Might need to set publicPath: './' (relative path)
  4. Check routing mode (SPA apps)

    • If using Vue Router or React Router in history mode
    • Refreshing page might 404 (server can’t find corresponding file)
    • Solutions:
      • Switch to hash mode (URL will have #)
      • Or add _redirects file in project root with content:
        /* /index.html 200

Real example: Last time I deployed my own Astro blog, page was blank. Investigated for ages, found output directory was set to public, changed to dist and it worked. Sometimes it really is that simple an error.

Problem 3: Style or Resource Loading Failed

Error appearance: Page displays but styles are all messed up, images won’t load, looks like there’s no CSS.

Troubleshooting steps:

  1. Open developer tools, check Network tab

    • See if CSS, JS, image files are 404
    • Check if these resource request paths are correct
  2. Check resource reference paths

    • Relative path vs absolute path issue
    • If HTML has /assets/style.css (absolute path) but deployed to subpath, won’t find it
    • Solutions: Use framework-provided resource handling methods
      • Astro: Use import to import resources
      • Hugo: Use .RelPermalink or absURL
      • Hexo: Use url_for() helper function
  3. Check CDN config

    • If using external CDN (like jsDelivr, cdnjs)
    • Confirm CDN links aren’t blocked
    • Can switch to domestic CDN (like BootCDN)

Real example: Previously helped a friend deploy Hexo blog, page displayed but no styles. Checked source code and found CSS path was /css/style.css, but actual file was at /blog/css/style.css. Problem was he deployed blog to subpath but didn’t change url and root in Hexo config file. Modified _config.yml, added root: /blog/, regenerated and it worked.

Quick Troubleshooting Checklist

When encountering problems, check in this order—usually solves them:

  1. ✓ View build log, find error message
  2. ✓ Confirm build command is correct (compare with config table)
  3. ✓ Confirm output directory is correct (compare with config table)
  4. ✓ Check if environment variables are set (Hugo projects must set HUGO_VERSION)
  5. ✓ Open browser F12, check console and network requests
  6. ✓ Check .gitignore, confirm no build artifacts pushed to Git
  7. ✓ Run npm run build or hugo locally, confirm local build works

If you’ve checked all these and it still doesn’t work, seek help on Cloudflare community forums or check the Troubleshooting section in official docs.

Advanced Tips: Making Your Blog More Professional

Blog’s online, but this is just the beginning. Here are some tips to make your blog more professional—not hard to implement but greatly improve experience.

Binding Custom Domain

Using a .pages.dev domain works fine, but your own domain is more professional. And it’s super simple to set up, with Cloudflare providing free SSL certificates.

Setup steps:

  1. Purchase a domain from a registrar (like GoDaddy, Alibaba Cloud, Tencent Cloud)
  2. Enter your Cloudflare Pages project, click Custom domains tab
  3. Click Set up a custom domain, enter your domain (like blog.example.com)
  4. Cloudflare will give you some DNS records, go back to domain registrar’s DNS management page and add these records
  5. Wait for DNS resolution to take effect (usually minutes to hours)
  6. After resolution takes effect, Cloudflare automatically configures HTTPS certificate

Pro tip: If your domain is also managed on Cloudflare, DNS resolution will be faster and can be configured automatically without manual record addition.

Build Optimization: Speeding Up Build Time

If your blog has many articles, build time might be long. Here are some optimization suggestions:

  1. Enable caching

    • Cloudflare Pages caches node_modules by default
    • If build is slow, check if it’s redownloading dependencies every time
  2. Reduce unnecessary dependencies

    • Check package.json, delete unused packages
    • Libraries that can load from CDN (like jQuery), don’t install in project
  3. Parallel builds

    • Hugo has --gc parameter to clean cache, sometimes speeds up builds
    • Astro can enable experimental.contentCollectionCache caching
  4. Branch strategy

    • Develop on dev branch, only merge to main when officially releasing
    • This way not every commit triggers production environment build

Performance Monitoring and Analytics

Want to know your blog’s traffic? Cloudflare provides free analytics tools.

View traffic data:

  1. Enter Cloudflare Pages project
  2. Click Analytics tab
  3. Can see:
    • Total visits (Requests)
    • Bandwidth usage (Bandwidth)
    • Visitor source countries (Requests by country)
    • Traffic trend graphs

Web Vitals performance monitoring:

  • Cloudflare also provides Web Vitals monitoring, showing page load speed, interaction latency, and other metrics
  • This data is especially useful for optimizing user experience
  • If you find a metric is poor, optimize specifically (like compressing images, lazy loading, etc.)

Automated Workflows

If you want further automation, combine with GitHub Actions to implement advanced features:

Example 1: Scheduled post publishing

  • Set future publish time after writing article
  • GitHub Actions checks on schedule, publishes when time comes

Example 2: Auto-generate sitemap

  • Auto-submit sitemap to search engines after each deployment

Example 3: Image compression

  • Auto-compress images before pushing, reducing load time

These features aren’t mandatory but can make blog operation more worry-free. If interested, research GitHub Actions—community has many ready-made templates.

Conclusion

After all that, deploying static blogs really isn’t complicated. The key is understanding two configs: build command and output directory. Just fill them correctly according to the config table above and you can avoid 90% of problems.

Let me summarize the core configs again—bookmark this table:

FrameworkBuild CommandOutput DirectoryRequired Env Var
Astronpm run builddist-
HugohugopublicHUGO_VERSION = 0.143.1
Hexohexo generatepublic-
Gatsbygatsby buildpublic-
Eleventynpx @11ty/eleventy_site-

Don’t panic when encountering problems either. Most are config mistakes. Check build log first, then compare with troubleshooting checklist in this article—usually solves them.

Go ahead and try now. Open Cloudflare Pages, connect your Git repository, fill in the correct config, and your blog will be online in 10 minutes.

If this article helped you, please share it with other friends struggling with blog deployment. If you encounter problems not mentioned here during deployment, feel free to comment—might help others too.

Happy deploying and happy writing!

Published on: Dec 1, 2025 · Modified on: Dec 4, 2025

Related Posts