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

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
| Framework | Build Command | Output Directory | Important Notes |
|---|---|---|---|
| Astro | npm run build | dist | Default works, SSR needs extra config |
| Hugo | hugo | public | Must set HUGO_VERSION environment variable! |
| Hexo | hexo generate | public | Some themes need NODE_VERSION |
| Gatsby | gatsby build | public | Simplest, rarely errors |
| Eleventy | npx @11ty/eleventy | _site | Note the underscore prefix |
| Next.js | npx opennextjs-cloudflare | .worker-next | 2025 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 buildor directastro 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:
hugoorhugo -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, like0.143.1, not0.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(shorthandhexo galso 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.3or18.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:
- Install dependency:
npm install @opennextjs/cloudflare - Build command:
npx opennextjs-cloudflare - 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:
- Code is pushed to GitHub or GitLab - Open your repository page and confirm latest code is there
- Project has package.json (if Node.js project) - Make sure dependencies are listed, not just installed locally without being in package.json
- 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.devdomain. For example, entermy-blogand your domain will bemy-blog.pages.dev. - Production branch: Production branch, usually
mainormaster. - 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:
hugoorhugo -b $CF_PAGES_URL - Hexo:
hexo generate - Gatsby:
gatsby build - Eleventy:
npx @11ty/eleventy - Next.js:
npx opennextjs-cloudflare
- Astro:
Build output directory: Output directory
- Astro:
dist - Hugo:
public - Hexo:
public - Gatsby:
public - Eleventy:
_site - Next.js:
.worker-next
- Astro:
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)
- Variable name:
Hexo projects (if needed):
- Variable name:
NODE_VERSION - Value:
14.3or18.17.0(based on your local version)
- Variable name:
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:
- Enter your Cloudflare Pages project
- Click the Settings tab at top
- Select Environment variables in left menu
- Click Add variable button
- Fill in variable name and value, click Save
Common environment variables:
HUGO_VERSION: Hugo version number (like0.143.1)NODE_VERSION: Node.js version number (like18.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:
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
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 buildinstead ofnpm run build(missingrun)
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 --saveautomatically adds it)
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)
- Set
- Hugo projects: 99% of build failures are from not setting HUGO_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:
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
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
publicinstead ofdist - Hugo project filled
distinstead ofpublic - Eleventy project filled
siteinstead of_site(missing underscore)
- Astro project filled
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'inastro.config.mjs - Vue/React projects: Might need to set
publicPath: './'(relative path)
- If deploying to subpath (like
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
_redirectsfile in project root with content:/* /index.html 200
- Switch to hash mode (URL will have
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:
Open developer tools, check Network tab
- See if CSS, JS, image files are 404
- Check if these resource request paths are correct
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
importto import resources - Hugo: Use
.RelPermalinkorabsURL - Hexo: Use
url_for()helper function
- Astro: Use
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:
- ✓ View build log, find error message
- ✓ Confirm build command is correct (compare with config table)
- ✓ Confirm output directory is correct (compare with config table)
- ✓ Check if environment variables are set (Hugo projects must set HUGO_VERSION)
- ✓ Open browser F12, check console and network requests
- ✓ Check .gitignore, confirm no build artifacts pushed to Git
- ✓ Run
npm run buildorhugolocally, 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:
- Purchase a domain from a registrar (like GoDaddy, Alibaba Cloud, Tencent Cloud)
- Enter your Cloudflare Pages project, click Custom domains tab
- Click Set up a custom domain, enter your domain (like
blog.example.com) - Cloudflare will give you some DNS records, go back to domain registrar’s DNS management page and add these records
- Wait for DNS resolution to take effect (usually minutes to hours)
- 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:
Enable caching
- Cloudflare Pages caches
node_modulesby default - If build is slow, check if it’s redownloading dependencies every time
- Cloudflare Pages caches
Reduce unnecessary dependencies
- Check package.json, delete unused packages
- Libraries that can load from CDN (like jQuery), don’t install in project
Parallel builds
- Hugo has
--gcparameter to clean cache, sometimes speeds up builds - Astro can enable
experimental.contentCollectionCachecaching
- Hugo has
Branch strategy
- Develop on
devbranch, only merge tomainwhen officially releasing - This way not every commit triggers production environment build
- Develop on
Performance Monitoring and Analytics
Want to know your blog’s traffic? Cloudflare provides free analytics tools.
View traffic data:
- Enter Cloudflare Pages project
- Click Analytics tab
- 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:
| Framework | Build Command | Output Directory | Required Env Var |
|---|---|---|---|
| Astro | npm run build | dist | - |
| Hugo | hugo | public | HUGO_VERSION = 0.143.1 |
| Hexo | hexo generate | public | - |
| Gatsby | gatsby build | public | - |
| Eleventy | npx @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

Complete Guide to Deploying Astro on Cloudflare: SSR Configuration + 3x Speed Boost for China

Building an Astro Blog from Scratch: Complete Guide from Homepage to Deployment in 1 Hour
