Skip to content

Cloudflare Pages

Deploy static sites (React, Vue, Astro, etc.) to Cloudflare Pages with automatic preview deployments and production branches.

Prerequisites

  1. Node.js and npm (or pnpm) installed
  2. Wrangler CLI available via npx
  3. A Cloudflare account with a Pages project already created
  4. A Cloudflare API token

Create the Pages Project

You must create the Cloudflare Pages project before deploying. The project name must exactly match the name field in your pilum.yaml.

Option A: Cloudflare Dashboard

  1. Go to Workers & Pages in the sidebar
  2. Click CreatePages
  3. Choose Direct Upload (not “Connect to Git” — Pilum handles the deploy)
  4. Name the project to match your pilum.yaml name field
  5. Click Create — you don’t need to upload anything

Option B: Wrangler CLI

Terminal window
npx wrangler pages project create my-site

API Token

Terminal window
# Create an API token:
# Cloudflare Dashboard → My Profile → API Tokens → Create Token
# Use the "Edit Cloudflare Workers" template or create custom with Pages permissions
# Verify it works
npx wrangler --version

Service Configuration

name: my-site
provider: cloudflare
cloudflare:
account_id: "abc123def456"
token_env: "CLOUDFLARE_API_TOKEN"
production_branch: "main"
package_manager: "npm"
build:
cmd: "npm run build"
output_dir: "dist"

Required Fields

FieldDescription
nameProject name (must match your Cloudflare Pages project name)
cloudflare.account_idCloudflare account ID

Optional Fields

Cloudflare Configuration

FieldTypeDefaultDescription
cloudflare.token_envstringCLOUDFLARE_API_TOKENEnvironment variable name containing the API token
cloudflare.production_branchstringmainBranch name that triggers production deployment
cloudflare.package_managerstringnpmPackage manager (npm or pnpm)

Build Configuration

FieldTypeDefaultDescription
build.cmdstringnpm run buildBuild command to run
build.output_dirstringdistDirectory containing built static files

Deployment Steps

The Cloudflare Pages recipe executes:

  1. install dependenciesnpm ci or pnpm install --frozen-lockfile
  2. build site — Run build command (skipped if no build.cmd configured)
  3. deploy to pages — Deploy via npx wrangler pages deploy

Production vs Preview Deploys

Pilum uses the --tag flag to determine deployment type:

  • Production: When tag matches production_branch (default: main) or is latest
  • Preview: Any other tag value creates a preview deployment
Terminal window
# Production deploy
pilum deploy --tag=main
# Preview deploy (e.g., from a feature branch)
pilum deploy --tag=feature-login

Preview deployments get a unique URL like https://<branch>.my-site.pages.dev.

Package Manager

npm (default)

cloudflare:
package_manager: "npm"

Installs with npm ci for reproducible builds from the lockfile.

pnpm

cloudflare:
package_manager: "pnpm"

Installs with pnpm install --frozen-lockfile.

pnpm Monorepo

For pnpm workspaces where the site is one package in a monorepo, set the build command to filter from the workspace root:

name: my-site
provider: cloudflare
cloudflare:
account_id: "abc123def456"
package_manager: "pnpm"
build:
cmd: "pnpm --filter @scope/my-site... build"
output_dir: "apps/my-site/dist"

The ... suffix builds the package AND all its workspace dependencies in order. The output_dir should point to the specific package’s dist folder relative to the monorepo root.

Build Step

The build step runs your site’s build command via shell:

build:
cmd: "npm run build"
output_dir: "dist"

If no build.cmd is set, the step is skipped automatically. The output_dir tells wrangler which directory to deploy.

Common output directories by framework:

FrameworkOutput Dir
Vite / React / Vuedist
Next.js (static)out
Astrodist
Create React Appbuild

Generated Deploy Script

Pilum generates a deploy script that:

  1. Validates the API token environment variable is set
  2. Exports CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID
  3. Deploys via npx wrangler pages deploy
Terminal window
if [ -z "$CLOUDFLARE_API_TOKEN" ]; then
echo "Error: CLOUDFLARE_API_TOKEN environment variable is not set"
exit 1
fi
export CLOUDFLARE_API_TOKEN="$CLOUDFLARE_API_TOKEN"
export CLOUDFLARE_ACCOUNT_ID="abc123def456"
npx wrangler pages deploy dist --project-name=my-site --branch=main

Example Commands

Terminal window
# Full deploy pipeline (build + deploy)
pilum deploy --tag=main
# Build only (no deploy)
pilum build
# Preview commands
pilum dry-run --tag=main
# Deploy only (assumes already built)
pilum deploy --only-tags=deploy --tag=main
# Preview deployment from feature branch
pilum deploy --tag=feature-auth

CI/CD Integration

GitHub Actions (pilum-action)

The recommended approach uses the official pilum-action:

name: Deploy
on:
push:
branches: [main]
workflow_call:
inputs:
tag:
required: true
type: string
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Deploy with Pilum
uses: SID-Technologies/pilum-action@v1
with:
command: deploy
services: my-site
tag: ${{ inputs.tag || github.ref_name }}
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}

GitHub Actions (manual install)

Alternatively, install Pilum directly:

name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install Pilum
run: |
curl -L https://github.com/SID-Technologies/Pilum/releases/latest/download/pilum-linux-amd64.tar.gz | tar xz
sudo mv pilum /usr/local/bin/
- name: Deploy
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
run: pilum deploy --tag=${{ github.ref_name }}

Both approaches deploy to production on pushes to main and can create preview deployments for feature branches.

Troubleshooting

Authentication Failed

Error: CLOUDFLARE_API_TOKEN environment variable is not set

Ensure the token is exported:

Terminal window
export CLOUDFLARE_API_TOKEN="your-token-here"

Project Not Found

Error: A request to the Cloudflare API failed. Could not find project

The name in your pilum.yaml must exactly match your Cloudflare Pages project name. Create the project first in the Cloudflare dashboard or via:

Terminal window
npx wrangler pages project create my-site

Wrong Output Directory

No files found in dist/

Check that build.output_dir matches where your framework outputs built files:

build:
cmd: "npm run build"
output_dir: "build" # e.g., for Create React App

Wrangler Not Found

npx: command not found: wrangler

Ensure Node.js and npm are installed. Wrangler is invoked via npx so it doesn’t need a global install.

Next Steps