Skip to content

Cloudflare Pages: Complete Deployment Guide

DodaTech Updated 2026-06-23 8 min read

Cloudflare Pages is a Jamstack deployment platform that builds and hosts frontend applications directly from your Git repositories. It integrates with Cloudflare's global edge network to deliver sites with near-zero latency and includes serverless functions for backend logic.

In this tutorial, you will learn to connect a Git repository to Cloudflare Pages, configure build settings and environment variables, manage preview deployments for pull requests, write serverless functions, set up custom domains, and handle redirects. DodaTech uses Cloudflare Pages to host the Doda Browser landing page and DodaZIP documentation site.

What You'll Learn

By the end of this guide, you will deploy a frontend application from GitHub to Cloudflare Pages, add serverless Functions for API endpoints, configure custom domains with automatic SSL, set up branch-based preview deployments, and implement redirect rules.

Why Cloudflare Pages Matters

Cloudflare Pages combines the developer experience of modern Jamstack platforms with the performance of Cloudflare's global CDN. Deployments happen automatically on every Git push, preview deployments appear for every pull request, and serverless Functions scale to zero when not in use. This makes it ideal for Web Servers teams practicing DevOps and continuous deployment.

Cloudflare Pages Learning Path

flowchart LR
  A[Git Repository] --> B[Build Configuration]
  B --> C[Preview Deployments]
  C --> D[Custom Domain]
  D --> E[Serverless Functions]
  E --> F{You Are Here}
  style F fill:#f90,color:#fff

Connecting a Git Repository

First, push your frontend project to GitHub, GitLab, or Bitbucket. Then connect via the Cloudflare Dashboard:

# Example: A basic React project pushed to GitHub
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/your-org/dodatech-landing.git
git branch -M main
git push -u origin main

Build configuration in Cloudflare Dashboard

Set these values in the Cloudflare Pages dashboard:

Setting Value
Framework preset React
Build command npm run build
Build output directory build
Root directory (leave empty)
Node.js version 18

Alternatively, configure with a _pages.yml or <a href="/web-servers-hosting/cloudflare/">cloudflare</a>.yaml in your repo:

name: dodatech-landing
pages:
  - repository: your-org/dodatech-landing
    branch: main
    framework: react
    build:
      command: npm run build
      directory: build
    environment:
      NODE_VERSION: "18"
      REACT_APP_API_URL: https://api.dodatech.com

Expected output

✔ Initializing build environment
✔ Installing dependencies (npm install)
✔ Running build command (npm run build)
✔ Uploading build directory (build)
✔ Deployed to: https://dodatech-landing.pages.dev

Preview Deployments

Every pull request gets its own preview URL:

# Create a new branch and PR
git checkout -b feature/new-hero
echo "Updated hero section" >> src/App.js
git add .
git commit -m "Update hero section"
git push -u origin feature/new-hero

Cloudflare Pages automatically builds and deploys:

# The preview URL follows this pattern:
# https://<hash>.<project>.pages.dev
# Example: https://abc123.dodatech-landing.pages.dev

You can set branch deployment rules:

# In your cloudflare.yaml or Pages dashboard
deploy:
  production: main
  preview:
    - feature/*
    - dev
    - staging/*
  branch_deploy: true
  pr_preview: true

Serverless Functions

Add backend logic without managing a server. Create a functions directory in your project root:

// functions/api/products.js
export async function onRequest(context) {
  const { request, env } = context;

  const products = [
    { id: 1, name: "Doda Browser", category: "browser" },
    { id: 2, name: "DodaZIP", category: "utilities" },
    { id: 3, name: "Durga Antivirus Pro", category: "security" }
  ];

  return new Response(JSON.stringify(products), {
    headers: { "Content-Type": "application/json" }
  });
}
// functions/api/products/[id].js
export async function onRequest(context) {
  const { request, env, params } = context;
  const productId = parseInt(params.id);

  const products = {
    1: { name: "Doda Browser", version: "5.2", downloads: 500000 },
    2: { name: "DodaZIP", version: "3.1", downloads: 120000 },
    3: { name: "Durga Antivirus Pro", version: "2026", downloads: 850000 }
  };

  const product = products[productId];
  if (!product) {
    return new Response("Not Found", { status: 404 });
  }

  return new Response(JSON.stringify(product), {
    headers: { "Content-Type": "application/json" }
  });
}

Testing functions locally with Wrangler

# Install Wrangler CLI
npm install -g wrangler

# Run Pages functions locally
wrangler pages dev ./build -- npm run start

Expected output

curl https://dodatech-landing.pages.dev/api/products
# [{"id":1,"name":"Doda Browser","category":"browser"},{"id":2,"name":"DodaZIP","category":"utilities"},{"id":3,"name":"Durga Antivirus Pro","category":"security"}]

curl https://dodatech-landing.pages.dev/api/products/1
# {"name":"Doda Browser","version":"5.2","downloads":500000}

Custom Domain and SSL

Add a custom domain in the Cloudflare Pages dashboard:

# In Cloudflare Dashboard > Pages > Your Project > Custom domains
# Add domain: www.dodatech.com
# DNS configuration (automatic if using Cloudflare DNS):
# Type: CNAME
# Name: www
# Target: dodatech-landing.pages.dev

Cloudflare automatically provisions a free SSL certificate. For redirects:

# In the Pages dashboard, add a redirect rule
# Source: /old-path
# Destination: /new-path
# Status: 301 (permanent) or 302 (temporary)

Headers and Redirects

Create a _headers file in your build output directory:

# /build/_headers
/assets/*
  Cache-Control: public, max-age=31536000, immutable

/api/*
  Access-Control-Allow-Origin: https://www.dodatech.com
  X-Content-Type-Options: nosniff

/*
  X-Frame-Options: DENY
  X-XSS-Protection: 1; mode=block
  Referrer-Policy: strict-origin-when-cross-origin

Create a _redirects file:

# /build/_redirects
/blog/*    https://blog.dodatech.com/:splat    301
/old-page  /new-page                            301
/docs       /docs/getting-started               302
/api/*      https://api.dodatech.com/:splat     200

Expected behavior

curl -I https://dodatech-landing.pages.dev/assets/style.css
# cache-control: public, max-age=31536000, immutable

curl -I https://dodatech-landing.pages.dev/old-page
# location: /new-page
# status: 301

Environment Variables

Manage environment variables per environment:

# Via Cloudflare Dashboard > Pages > Your Project > Environment variables
# Production:
NODE_VERSION=18
API_URL=https://api.dodatech.com
SENTRY_DSN=https://example@sentry.io/123

# Preview:
NODE_VERSION=18
API_URL=https://staging-api.dodatech.com

Access them in your build:

# In your build script (package.json)
"build": "REACT_APP_API_URL=$API_URL npm run build"

Common Errors

1. Build Fails with Out of Memory

Cloudflare Pages has a 1024 MB memory limit for builds. Reduce memory usage by disabling source maps (GENERATE_SOURCEMAP=false) or splitting large builds.

2. Functions Return 404

The function file path must match the URL path. A file at functions/api/products.js serves at /api/products. Files named [param].js match dynamic segments.

3. Custom Domain Not Working

DNS propagation can take up to 24 hours. Verify the CNAME record points to your-project.pages.dev. If using Cloudflare DNS, ensure the orange cloud (proxy) is enabled.

4. Redirects Not Applying

The _redirects file must be in the build output directory, not the project root. Check that it is included in the deployed artifacts.

5. Environment Variables Not Available in Build

Build-time variables must be prefixed with REACT_APP_ (for Create React App) or configured to be public. Secret variables are not available at build time by default.

Practice Questions

1. How does Cloudflare Pages differ from Cloudflare Workers? Cloudflare Pages is a static site host with serverless functions. Cloudflare Workers are standalone serverless functions that run at the edge. Pages Functions are built on Workers but are scoped to a Pages project.

2. What happens when you push to a non-production branch? Cloudflare Pages creates a preview deployment with a unique URL. The deployment is built using the branch's code and is accessible at <hash>.<project>.pages.dev.

3. How do you add a serverless function to a Pages project? Create a functions directory in the project root. Each .js or .ts file in this directory becomes an endpoint. Use export async function onRequest(context) to handle requests.

4. Challenge: Blog with serverless CMS

Build a serverless blog on Cloudflare Pages:

  • Static frontend using a framework of your choice
  • Functions that read markdown files from a KV namespace
  • Tag-based filtering via query parameters
  • Preview deployments for draft articles

Mini Project: Full Jamstack Deployment

Deploy a complete Jamstack application on Cloudflare Pages:

  1. Create a React or static site with a build output directory
  2. Add a _headers file with security headers and caching rules
  3. Add a _redirects file with at least two redirect rules
  4. Create a serverless function that returns product data
  5. Connect the repo to Cloudflare Pages
  6. Configure a custom domain with automatic SSL
  7. Create a PR and verify the preview deployment
# Verify headers
curl -I https://your-project.pages.dev/index.html | grep -i "x-frame-options"

# Verify function
curl https://your-project.pages.dev/api/products

# Verify redirect
curl -I https://your-project.pages.dev/old-page

This setup mirrors how DodaTech deploys marketing pages and Doda Browser documentation.

FAQ

How is Cloudflare Pages different from Netlify or Vercel?

Cloudflare Pages offers unlimited bandwidth and requests with no overage charges. Its edge network covers more locations globally. Netlify and Vercel have stronger serverless runtime features and larger function execution limits.

Can I use Cloudflare Pages with a framework like Next.js?

Yes. Next.js is supported with specific configuration. Cloudflare Pages supports static export and the @<a href="/web-servers-hosting/cloudflare/">cloudflare</a>/next-on-pages adapter for SSR mode.

What are the build limits on the free plan?

The free plan includes 500 builds per month, 500 functions per project, and 1 GB of storage. Each function can execute for up to 30 seconds (free) or 60 seconds (paid).

Does Cloudflare Pages support monorepos?

Yes. Configure the root directory in the build settings to point to your sub-project. Each sub-project can be deployed independently.

How do I handle form submissions without a backend?

Use Cloudflare Pages Functions to handle form POST requests. The function can send emails via SendGrid, write to KV storage, or forward to an external API.

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

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro