A complete walkthrough for deploying static sites on Cloudflare Pages

Cloudflare Pages is the platform I deploy most personal sites to. Static blog, documentation site, marketing page for a side project, anything that does not require server-side rendering with framework-specific behavior. The combination of unlimited bandwidth on the free tier, generous build minutes, and Cloudflare’s overall network quality makes it the best default for individuals and small teams.

This walkthrough covers a complete Cloudflare Pages setup from a fresh GitHub repo to a custom domain serving production traffic. By the end you will have a working static site, with HTTPS, custom domain, deploy previews on every pull request, and the basic patterns for ongoing changes.

What you will need

A Cloudflare account (free).

A GitHub or GitLab account with a repository containing your site source.

A domain name (optional but recommended). You can use the auto-generated *.pages.dev subdomain Cloudflare gives you, but a custom domain is what you actually want for anything serious.

About 30 minutes for the initial setup, plus some time for the DNS propagation step.

What you can build with this

Cloudflare Pages handles static sites well. The supported build patterns include:

  • Static site generators: Hugo, Jekyll, 11ty, Astro (static mode), Next.js (static export), Nuxt (static)
  • Vanilla HTML/CSS/JS sites with no build step
  • React, Vue, Svelte single-page applications
  • Documentation generators: VuePress, MkDocs, Docusaurus
  • Marketing site generators: Webflow exports, framework-built sites

Server-side rendering is partially supported through Cloudflare Functions (similar to AWS Lambda), but if you need substantial server-side logic, Vercel or your own server might be a better fit. Pure static sites are where Cloudflare Pages shines.

Step 1, prepare your repository

Your repository needs to contain the source code for your site. The structure depends on your generator.

For Hugo:

your-site/
  ├── content/
  ├── themes/
  ├── config.toml

Build command: hugo
Output directory: public

For 11ty:

your-site/
  ├── src/
  ├── package.json
  ├── .eleventy.js

Build command: npm run build
Output directory: _site

For Astro:

your-site/
  ├── src/
  ├── package.json
  ├── astro.config.mjs

Build command: npm run build
Output directory: dist

For a vanilla HTML site (no build step):

your-site/
  ├── index.html
  ├── styles.css

Build command: (empty)
Output directory: / or .

Push your repository to GitHub. Make sure the main branch contains the latest code.

Step 2, create the Pages project

Log in to the Cloudflare dashboard. Navigate to: Workers & Pages, then Pages tab.

Click “Connect to Git.” Authorize Cloudflare to access your GitHub account (or GitLab if you use that). Select the repository.

You will be prompted for build settings:

  • Production branch: typically main
  • Build command: as above for your framework
  • Build output directory: as above
  • Root directory: leave blank unless your site is in a subdirectory of the repo
  • Environment variables: usually none needed for basic builds

Click “Save and Deploy.”

The first build typically takes 30 seconds to 3 minutes depending on the project size and which framework. You can watch the build log in real time. If it succeeds, your site is now live at https://your-project.pages.dev.

Visit the URL and confirm it works.

Step 3, configure custom domain

The auto-generated .pages.dev URL is fine for previews; for anything real, you want your own domain.

In your Pages project, go to: Custom domains, Set up a custom domain.

Enter the domain (e.g., mysite.com) or subdomain (e.g., blog.mysite.com).

If your domain is already on Cloudflare DNS (you registered it through Cloudflare or transferred DNS to Cloudflare), the setup is automatic. Cloudflare creates the necessary DNS records and provisions the SSL certificate.

If your domain is on another DNS provider, you need to add a CNAME record pointing to your Pages project URL:

CNAME mysite.com → your-project.pages.dev

For an apex domain (no subdomain), CNAME flattening is needed; many DNS providers (including Cloudflare itself if you migrate DNS) support this. Cloudflare’s docs provide specific instructions per registrar.

After DNS propagation (usually a few minutes, occasionally up to an hour), your site is live at the custom domain with automatic HTTPS.

Step 4, the deploy preview workflow

This is the feature that makes Cloudflare Pages genuinely productive.

For every pull request you open against your main branch, Cloudflare automatically builds and deploys a preview. The preview URL is unique per PR (https://branch-name.your-project.pages.dev). Reviewers can click the link and see exactly what the change looks like in production-equivalent rendering.

The preview workflow is enabled by default once you connect the repository. You do not need additional configuration.

For collaborative projects, this is transformative. Designers and editors who do not want to clone the repo and run a local build can review changes by clicking a link.

Step 5, manage build settings over time

As your site grows, you might need to adjust build settings. The most common adjustments:

Environment variables. If your build process depends on API keys or feature flags, set them in: Settings, Environment variables. They are encrypted at rest and exposed only to your build process.

Build cache. Cloudflare automatically caches dependencies between builds (node_modules, etc.) to speed up rebuilds. If a dependency update needs a clean build, you can purge the cache from the Settings page.

Build environment. By default, builds run on Cloudflare’s standard environment with current Node.js, common build tools available. If you need a specific Node.js version or other tooling, set the environment variable NODE_VERSION to the version you need.

Build deploy frequency. Cloudflare Pages allows up to 500 builds per month on the free tier. For most projects this is far more than needed. Watch usage in: Settings, Plans.

Step 6, advanced features that you might want eventually

Cloudflare Pages plus Cloudflare Functions lets you add small server-side logic without leaving the platform. Functions are deployed automatically with your build if you have a functions/ directory in your project.

Cloudflare R2 (S3-compatible object storage) integrates with Pages for storing assets that should not be in your repo. Free tier is generous; pricing for larger storage is competitive.

Cloudflare D1 (SQLite-as-a-service) lets you build database-backed apps on top of Pages plus Functions. Still relatively new but maturing.

Cloudflare KV (key-value storage) is useful for things like form submission storage, simple caches, feature flags.

For purely static sites, you do not need any of these. They become useful when your site grows beyond static.

Step 7, monitoring and analytics

Cloudflare Web Analytics is built in. Privacy-respecting, no cookies, no personal data collected. Enable it in: Settings, Web Analytics. The data is genuinely useful for understanding traffic sources and basic page metrics.

For more detailed analytics, you can integrate Plausible, Fathom, or any other privacy-respecting analytics by adding their script to your site template.

For real user monitoring (RUM), Cloudflare Speed Brain is available on paid plans.

For uptime monitoring, use UptimeRobot (free) or a similar external service rather than relying on Cloudflare to alert you to its own outages.

Step 8, what to skip

A few things you might be tempted to enable but should not:

Cloudflare Workers as a routing layer for a static site. Adds complexity for no benefit on a pure static project.

Multiple frameworks in one project. Pick one. Cloudflare Pages can handle a monorepo, but a project that uses both Next.js and Hugo for different sections is asking for build complexity.

Custom build images. The default Cloudflare build environment handles 95 percent of common projects. Custom images are for specialized cases.

Aggressive caching headers via the underlying Cloudflare CDN. Unless you understand exactly what you are doing, the defaults are good.

Pricing reality

Cloudflare Pages free tier:

  • Unlimited bandwidth
  • 500 builds per month
  • 100 deploys per day
  • Up to 20,000 files per site
  • Up to 25 MB per file

For 95 percent of personal projects and small teams, the free tier is permanent.

If you need more (high build volume, large file counts), the Pro tier is $20 per month and adds priority builds, more concurrent builds, and various other features.

Compare to:

  • Vercel Hobby (free): 100 GB bandwidth limit, restrictive commercial-use terms
  • Netlify Free: 100 GB bandwidth, 300 build minutes, restrictive commercial use
  • AWS S3 + CloudFront: charged per GB

Cloudflare Pages is the most generous free tier in the category. The unlimited bandwidth specifically matters when your site occasionally goes viral.

Common problems and fixes

The build fails with “build command failed.” Usually a Node.js version mismatch. Set NODE_VERSION environment variable to match your local version (e.g., 20).

The site loads but assets 404. Usually a path-prefix issue. Check that your site generator is producing relative paths or absolute paths matching your domain root.

DNS does not resolve. Wait longer. DNS propagation can take up to an hour, occasionally longer for some networks.

The custom domain shows the wrong site. You may have multiple Pages projects with similar domain names. Check Settings, Custom domains for clean state.

Builds suddenly take longer than they used to. You may have hit the build cache size limit, or your dependencies have grown. Both are visible in the build logs.

Why this is the right answer for personal sites

Cloudflare Pages is, in 2026, the best free static site hosting for individuals and small teams. The unlimited bandwidth removes the anxiety about traffic spikes. The integration with Cloudflare’s broader product suite (DNS, CDN, R2, Workers) gives you a path to add more sophisticated functionality if needed without changing platforms. The developer experience is competitive with Vercel and Netlify on the things that matter.

The only common reason to pick something else is if you are deeply invested in Vercel-specific Next.js features (App Router with server components, Vercel Image Optimization, etc.). For most other use cases, Cloudflare Pages is the right default.

Cloudflare Pages | Cloudflare Pages docs

Related: Static site hosting in 2026, Domain registrar in 2026, VPS decision framework