React Deploy to Cloudflare Pages

react-deploy-pages@1.0.0 Template

Build a React web app and publish it to Cloudflare Pages, with per-branch previews.

Start from it

flightstack template use react-deploy-pages

What it does

Install, build and deploy a React web app to Cloudflare Pages in one job, asserting the built bundle before upload. Deploying a non-production branch produces a preview URL rather than touching the live site.

Inputs

projectName string required
The Cloudflare Pages project to deploy to.
branch string
Branch to deploy as. Empty uses the branch that triggered the run, which is what makes non-production branches land as previews.
workingDir string default .
Directory holding package.json.
outputDir string default dist
Directory the build writes to, and what gets uploaded.
build boolean default true
Install dependencies and build before deploying.
buildScript string default build
The npm script that produces the production bundle.
packageManager auto | npm | pnpm | yarn | bun default auto
Which package manager to use.
env object
Build-time environment variables, compiled INTO the bundle and therefore public. Never put a secret here.
mustContain array
Strings that must appear in the built JavaScript.
mustNotContain array
Strings that must NOT appear, checked before the upload.
include string default *.js
Filename pattern the assertions are checked against.
wranglerVersion string default latest
Version of wrangler to run via npx.

Definition

name: React Deploy to Cloudflare Pages
description: >-
  Build a React web app and publish it to Cloudflare Pages, with per-branch
  preview deployments.

triggers:
  - type: push
    branches: [main]

jobs:
  deploy:
    name: Deploy to Pages
    type: plugin/react-deploy-pages
    with:
      projectName: postwire-console
      outputDir: apps/console/dist
      env:
        VITE_API_URL: https://api.postwire.ai
      mustNotContain:
        - "localhost:"

plugin:
  name: react-deploy-pages
  displayName: React Deploy to Cloudflare Pages
  description: >-
    Install, build and deploy a React web app to Cloudflare Pages. Deploying a
    non-production branch produces a preview URL rather than touching the live
    site.
  category: deploy

  requiredTools:
    - name: nodejs
      version: ">=20.0.0"

  supportedPlatforms:
    - linux
    - macos
    - windows

  parameters:
    type: object
    properties:
      projectName:
        type: string
        description: The Cloudflare Pages project to deploy to.
      branch:
        type: string
        default: ""
        description: >-
          Branch to deploy as. Empty uses the branch that triggered the run,
          which is what makes non-production branches land as previews.
      workingDir:
        type: string
        default: "."
        description: Directory holding package.json.
      outputDir:
        type: string
        default: dist
        description: Directory the build writes to, and what gets uploaded.
      build:
        type: boolean
        default: true
        description: Install dependencies and build before deploying.
      buildScript:
        type: string
        default: build
        description: The npm script that produces the production bundle.
      packageManager:
        type: string
        enum: [auto, npm, pnpm, yarn, bun]
        default: auto
        description: Which package manager to use.
      env:
        type: object
        description: >-
          Build-time environment variables, compiled INTO the bundle and
          therefore public. Never put a secret here.
      mustContain:
        type: array
        description: Strings that must appear in the built JavaScript.
      mustNotContain:
        type: array
        description: Strings that must NOT appear, checked before the upload.
      include:
        type: string
        default: "*.js"
        description: Filename pattern the assertions are checked against.
      wranglerVersion:
        type: string
        default: latest
        description: Version of wrangler to run via npx.
    required: [projectName]

  script: |
    set -euo pipefail
    cd "{{workingDir}}"

    if [ -z "${CLOUDFLARE_API_TOKEN:-}" ] || [ -z "${CLOUDFLARE_ACCOUNT_ID:-}" ]; then
      echo "No Cloudflare credentials." >&2
      echo "Set CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID as pipeline secret variables." >&2
      exit 1
    fi

    pm="{{packageManager}}"
    if [ "$pm" = "auto" ]; then
      if [ -f pnpm-lock.yaml ]; then pm=pnpm
      elif [ -f yarn.lock ]; then pm=yarn
      elif [ -f bun.lockb ] || [ -f bun.lock ]; then pm=bun
      else pm=npm
      fi
    fi

    case "$pm" in
      pnpm|yarn) corepack enable >/dev/null 2>&1 || true ;;
    esac

    {{#build}}
    echo "--- installing dependencies"
    case "$pm" in
      npm)  if [ -f package-lock.json ]; then npm ci; else npm install; fi ;;
      pnpm) pnpm install --frozen-lockfile ;;
      yarn) yarn install --immutable || yarn install --frozen-lockfile ;;
      bun)  bun install --frozen-lockfile ;;
    esac

    echo "--- building"
    {{#each env}}
    export {{@key}}="{{this}}"
    {{/each}}
    "$pm" run "{{buildScript}}"
    {{/build}}

    out="{{outputDir}}"
    if [ ! -d "$out" ]; then
      echo "nothing to deploy: '$out' does not exist" >&2
      exit 1
    fi

    failed=0
    {{#each mustContain}}
    if grep -rqF --include="{{include}}" -- '{{this}}' "$out"; then
      echo "ok: bundle contains '{{this}}'"
    else
      echo "FAIL: '{{this}}' is missing from the bundle - refusing to deploy" >&2
      failed=1
    fi
    {{/each}}
    {{#each mustNotContain}}
    if grep -rqF --include="{{include}}" -- '{{this}}' "$out"; then
      echo "FAIL: '{{this}}' appears in the bundle - refusing to deploy" >&2
      failed=1
    else
      echo "ok: bundle is free of '{{this}}'"
    fi
    {{/each}}
    [ "$failed" = "0" ] || exit 1

    # The triggering ref is a full ref name often enough to matter
    # (refs/heads/main); Pages wants the short branch.
    branch="{{branch}}"
    if [ -z "$branch" ]; then
      branch="{{BRANCH}}"
    fi
    branch="${branch#refs/heads/}"

    echo "--- deploying to Pages project '{{projectName}}' as branch '$branch'"
    npx --yes wrangler@{{wranglerVersion}} pages deploy "$out" \
      --project-name "{{projectName}}" \
      --branch "$branch" \
      --commit-hash "{{COMMIT_SHA}}"