Deploy a Static Site to Cloudflare Pages
TL;DR
Cloudflare Pages is a JAMstack hosting platform with a generous free tier, global CDN, and native GitHub/GitLab integration. This guide walks through creating a Pages project, connecting your repo, configuring build settings, adding a custom domain, and using the Wrangler CLI as an alternative to the dashboard.
Prerequisites
- A Cloudflare account (free at cloudflare.com)
- A GitHub or GitLab repository containing your static site source
- Node.js 18+ installed locally
- A domain name (optional for custom domain step)
What Is Cloudflare Pages?
Cloudflare Pages serves static assets from Cloudflare's global network of over 300 data centres. Every deployment generates an immutable preview URL, and production deployments update your custom domain automatically. The free tier includes unlimited requests, 500 builds per month, and 100 custom domains.
It competes directly with Netlify and Vercel for static hosting, but the key differentiator is Cloudflare's network performance and the ability to add Workers functions alongside your static files without changing platforms. For a comparison with Vercel's approach, see the guide on deploying a React app to Vercel.
Step 1: Create a Cloudflare Pages Project
- Log in to your Cloudflare dashboard at
dash.cloudflare.com. - In the left sidebar, select Workers and Pages.
- Click Create and then select the Pages tab.
- You will be prompted to connect a Git provider. Choose Connect to Git.
Cloudflare will ask you to authorise the GitHub or GitLab OAuth app. Grant it access to the specific repositories you want to deploy, not your entire account.
Step 2: Connect Your GitHub Repository
- After authorising, you will see a list of your repositories.
- Select the repository containing your static site.
- Click Begin setup.
If your repository is not listed, check that the Cloudflare OAuth app has access to it in your GitHub settings under Applications > Authorised OAuth Apps.
Step 3: Configure Build Settings
This is the most important step for frameworks that require a build process. Cloudflare Pages needs to know how to build your site.
| Framework | Build Command | Output Directory |
|---|---|---|
| Plain HTML | (leave blank) | / or /public |
| Astro | npm run build |
dist |
| Next.js (static export) | npm run build |
out |
| Hugo | hugo |
public |
| Jekyll | jekyll build |
_site |
| Eleventy | npx @11ty/eleventy |
_site |
Fill in:
- Project name: This becomes your
<project>.pages.devsubdomain - Production branch: Typically
mainormaster - Build command: See table above for your framework
- Build output directory: See table above
Environment variables: If your build requires API keys or feature flags, add them here. Use placeholder values during testing:
PUBLIC_API_URL=https://api.example.com
SITE_URL=https://yourdomain.com
Never commit real secrets to your repository. Add them as encrypted environment variables in the Cloudflare dashboard only.
Click Save and Deploy.
Step 4: Monitor Your First Build
Cloudflare Pages will clone your repository and run your build command. You can watch the build logs in real time in the dashboard.
A typical successful build log looks like this:
13:42:01.000 Cloning repository...
13:42:03.000 Using Node.js version 18.x
13:42:04.000 Running npm install
13:42:18.000 Running npm run build
13:42:22.000 Build completed successfully
13:42:22.000 Deploying assets...
13:42:24.000 Deployment complete: https://abc123.your-project.pages.dev
If the build fails, the most common causes are:
- Missing
package.jsonorpackage-lock.json - Incorrect build output directory path
- Missing environment variables that the build process requires
- Node.js version mismatch (set
NODE_VERSIONin environment variables if needed)
Step 5: Add a Custom Domain
Once your first build succeeds:
- In your Pages project, go to the Custom domains tab.
- Click Set up a custom domain.
- Enter your domain name (for example,
www.yourdomain.comoryourdomain.com). - Cloudflare will check whether your domain is already using Cloudflare DNS.
If your domain is on Cloudflare DNS (recommended): Cloudflare will automatically add the required CNAME record. Your domain will be live within a few minutes.
If your domain is on external DNS: Cloudflare will show you a CNAME record to add at your registrar:
Type: CNAME
Name: www
Value: your-project.pages.dev
SSL certificates are provisioned automatically via Let's Encrypt. You do not need to configure anything beyond adding the DNS record.
Step 6: Set Up Automatic Deployments
Every push to your production branch now triggers a new build and deployment automatically. Every push to any other branch generates a preview deployment at a unique URL -- useful for reviewing changes before merging.
To control which branches trigger builds:
- Go to Settings > Builds and deployments in your Pages project.
- Under Branch deployments, configure include and exclude patterns.
Example: deploy only main and branches prefixed with release/:
Include: main, release/*
Exclude: *
Alternative: Deploy with Wrangler CLI
The Wrangler CLI lets you deploy directly from your terminal without connecting a Git repository. This is useful for one-off deploys or CI/CD pipelines where you want full control.
Install Wrangler:
npm install -g wrangler
Authenticate:
wrangler login
This opens a browser window for OAuth authentication. Your credentials are stored locally in ~/.wrangler/config.
Deploy a static directory:
wrangler pages deploy ./dist --project-name=your-project-name
Replace ./dist with your build output directory and your-project-name with the project you created in the dashboard.
Create a new project via CLI (first deploy only):
wrangler pages deploy ./dist --project-name=your-new-project --branch=main
Wrangler will create the project automatically if it does not exist.
Useful Wrangler flags:
# Deploy to a specific branch (creates preview URL)
wrangler pages deploy ./dist --project-name=my-site --branch=staging
# Show deployment URL after deploy
wrangler pages deploy ./dist --project-name=my-site --commit-message="v1.2.0"
CI/CD Integration
To automate deploys from GitHub Actions without using the native Git integration (for example, if you want to run tests before deploying):
# .github/workflows/deploy.yml
name: Deploy to Cloudflare Pages
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
env:
PUBLIC_API_URL: ${{ secrets.PUBLIC_API_URL }}
- name: Deploy to Cloudflare Pages
uses: cloudflare/pages-action@v1
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
projectName: your-project-name
directory: dist
branch: main
Store your CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID as GitHub repository secrets. Never hardcode credentials in workflow files. For more on sitemap and URL automation that complements this workflow, see the guide on IndexNow and sitemap automation.
Troubleshooting Common Issues
Build succeeds but site shows old content Cloudflare Pages caches aggressively. Hard refresh with Ctrl+Shift+R (Windows/Linux) or Cmd+Shift+R (Mac). If the issue persists, check that your build output directory is correct and that the build is actually running.
"Build failed: No output directory found" Your build command ran but produced output in a different directory than configured. Check the build logs to see where files were written, then update the output directory setting to match.
Custom domain shows "522 Connection timed out"
If your domain uses an external proxy or CDN in addition to Cloudflare, you may have a routing loop. Point the domain directly to your-project.pages.dev via CNAME without additional proxying.
Environment variables not available during build Variables must be added to the Build environment, not the Preview or Production runtime environment. Double-check which environment tab you added them to in the dashboard.
FAQ
Is Cloudflare Pages free for commercial use? Yes. The free tier supports unlimited sites, requests, and bandwidth. The only limits are 500 builds per month and a maximum of 20,000 files per deployment. The paid Pro plan removes these limits and adds more concurrent builds.
Can I run server-side code on Cloudflare Pages?
Yes, via Cloudflare Workers Functions. Create a /functions directory in your project root and add JavaScript or TypeScript files. These deploy as edge functions alongside your static assets. This is Cloudflare's equivalent of Vercel's serverless functions.
How do I roll back a deployment? In the Pages dashboard, go to the Deployments tab, find the deployment you want to restore, and click Rollback to this deployment. Rollbacks are instant and do not require a rebuild.
Does Cloudflare Pages support server-side rendering? Not natively for frameworks like Next.js App Router or Nuxt 3 in SSR mode. You can use Cloudflare Workers for edge rendering, but this requires additional configuration beyond the standard Pages setup.
Can I use multiple custom domains for the same project? Yes. You can add up to 100 custom domains per project on the free plan, including apex domains and subdomains.
For building the content that goes on your static site, explore 1000+ free AI tools to speed up your writing and design workflow. For the next step after deploying -- getting your new site indexed -- read the guide on IndexNow and sitemap automation.