, 4 min read

Hosting Static Content with Cloudflare

I wrote about hosting static sites on various platforms:

  1. Hosting Static Content with surge.sh
  2. Hosting Static Content with now.sh, now.sh renamed themself to vercel.app
  3. Hosting Static Content with netlify.app

Since end of 2021 Cloudflare greatly enhanced their static site offering: Cloudflare Pages Goes Full Stack.

Start with npm install wrangler. This will install the JavaScript command to control your "Cloudflare Pages" account. The wrangler command has the following options:

$ wrangler

Commands:
  wrangler docs [command..]            ๐Ÿ“š Open wrangler's docs in your browser
  wrangler init [name]                 ๐Ÿ“ฅ Initialize a basic Worker project, including a wrangler.toml file
  wrangler generate [name] [template]  โœจ Generate a new Worker project from an existing Worker template. See https://github.com/cloudflare/templates
  wrangler dev [script]                ๐Ÿ‘‚ Start a local server for developing your worker
  wrangler deploy [script]             ๐Ÿ†™ Deploy your Worker to Cloudflare.  [aliases: publish]
  wrangler delete [script]             ๐Ÿ—‘  Delete your Worker from Cloudflare.
  wrangler tail [worker]               ๐Ÿฆš Starts a log tailing session for a published Worker.
  wrangler secret                      ๐Ÿคซ Generate a secret that can be referenced in a Worker
  wrangler secret:bulk [json]          ๐Ÿ—„  Bulk upload secrets for a Worker
  wrangler kv:namespace                ๐Ÿ—‚  Interact with your Workers KV Namespaces
  wrangler kv:key                      ๐Ÿ”‘ Individually manage Workers KV key-value pairs
  wrangler kv:bulk                     ๐Ÿ’ช Interact with multiple Workers KV key-value pairs at once
  wrangler pages                       โšก Configure Cloudflare Pages
  wrangler queues                      ๐Ÿ‡ถ Configure Workers Queues
  wrangler r2                          ๐Ÿ“ฆ Interact with an R2 store
  wrangler dispatch-namespace          ๐Ÿ“ฆ Interact with a dispatch namespace
  wrangler d1                          ๐Ÿ—„  Interact with a D1 database
  wrangler constellation               ๐Ÿค– Interact with Constellation models
  wrangler pubsub                      ๐Ÿ“ฎ Interact and manage Pub/Sub Brokers
  wrangler mtls-certificate            ๐Ÿชช Manage certificates used for mTLS connections
  wrangler login                       ๐Ÿ”“ Login to Cloudflare
  wrangler logout                      ๐Ÿšช Logout from Cloudflare
  wrangler whoami                      ๐Ÿ•ต  Retrieve your user info and test your auth config
  wrangler types                       ๐Ÿ“ Generate types from bindings & module rules in config
  wrangler deployments                 ๐Ÿšข List and view details for deployments
  wrangler rollback [deployment-id]    ๐Ÿ”™ Rollback a deployment

Flags:
  -j, --experimental-json-config  Experimental: Support wrangler.json  [boolean]
  -c, --config                    Path to .toml configuration file  [string]
  -e, --env                       Environment to use for operations and .env files  [string]
  -h, --help                      Show help  [boolean]
  -v, --version                   Show version number  [boolean]

And specifically for the pages subcommand:

$ wrangler pages

โšก Configure Cloudflare Pages

Commands:
  wrangler pages dev [directory] [-- command..]  ๐Ÿง‘๐Ÿ’ป Develop your full-stack Pages application locally
  wrangler pages project                         โšก Interact with your Pages projects
  wrangler pages deployment                      ๐Ÿš€ Interact with the deployments of a project
  wrangler pages deploy [directory]              ๐Ÿ†™ Deploy a directory of static assets as a Pages deployment  [aliases: publish]

Flags:
  -j, --experimental-json-config  Experimental: Support wrangler.json  [boolean]
  -c, --config                    Path to .toml configuration file  [string]
  -e, --env                       Environment to use for operations and .env files  [string]
  -h, --help                      Show help  [boolean]
  -v, --version                   Show version number  [boolean]

To deploy your current directory to Cloudflare, see Use Direct Upload with continuous integration:

CLOUDFLARE_ACCOUNT_ID=<ACCOUNT_ID> npx wrangler pages publish <DIRECTORY> --project-name=<PROJECT_NAME>

Your account id is this 32 byte long hash, not your e-mail address.

The so called "project name" is your previously specified name for your pages. In my case it is klm. Therefore I run:

$ time CLOUDFLARE_ACCOUNT_ID='d4ba2e3c15c942c374380afd7fb7f441' wrangler pages deploy --project-name=klm .
Attempting to login via OAuth...
Opening a link in your default browser: https://dash.cloudflare.com/oauth2/(...)
Successfully logged in.
๐ŸŒ  Uploading... (1014/1014)

โœจ Success! Uploaded 1014 files (88.23 sec)

โœจ Deployment complete! Take a peek over at https://3493e64d.klm.pages.dev
        real 118.45s
        user 4.63s
        sys 0
        swapped 0
        total space 0

Deploying more than 1,000 files takes around two minutes. Some time has to be substracted from this as I had to log in manually via browser.

If you have already uploaded and just want to change some files, then deployment is much faster.

$ time CLOUDFLARE_ACCOUNT_ID='2a73fd651205801dfe83244b968920bb' wrangler pages deploy . --project-name=klm
๐ŸŒŽ  Uploading... (1023/1023)

โœจ Success! Uploaded 9 files (1014 already uploaded) (2.92 sec)

โœจ Deployment complete! Take a peek over at https://e885abe0.klm.pages.dev
        real 11.29s
        user 1.80s
        sys 0
        swapped 0
        total space 0

My static site on Cloudflare is here: klm.pages.dev.

Added 23-May-2023: Instead of setting CLOUDFLARE_ACCOUNT environment variable in front of wrangler, you have to first login via

wrangler login

Then

npx wrangler pages deploy <DIRECTORY> --project-name=<PROJECT_NAME>

In my case this is

$ time wrangler pages deploy . --project-name=klm

Added 29-Aug-2023: wrangler script seems to be broken. It emits below error message:

โœ˜ [ERROR] A request to the Cloudflare API (/accounts/Elmar.Klausmeier@gmail.com/pages/projects/klm) failed.

  Could not route to /client/v4/accounts/Elmar.Klausmeier@gmail.com/pages/projects/klm, perhaps your
  object identifier is invalid? [code: 7003]

  If you think this is a bug, please open an issue at:
  https://github.com/cloudflare/workers-sdk/issues/new/choose

Remedy: Go to your dashboard in Cloudflare, remove the "project", then upload zip-file with all your files.

Added 24-Sep-2023: Previously you had to use your e-mail address, i.e., your accound id. Now you have to use your Account ID, which is this 32 byte long hash. If you still use your e-mail address, you will get below error:

โœ˜ [ERROR] A request to the Cloudflare API (/accounts/Elmar.Klausmeier@gmail.com/pages/projects) failed.

See BUG: #3862.

Added 02-Jul-2024: Latest twist:

time wrangler pages deploy --project-name klm .

Added 15-Aug-2026: Cloudflare likes to play around with its wrangler script. The latest way to upload is:

time wrangler pages publish --project-name klm .

Also, node must not be too current. This version is good: nodejs-lts-krypton 24. Higher versions do not work.