I was recently exploring options on how to deploy a WordPress site as a static site when I found this article. The official documentation for Cloudflare Pages suggests that users export a static snapshot of their WordPress site with a plugin, and manually upload that (.zip) file in the Cloudflare dashboard…
So I started reading the source code of the Cloudflare Pages CLI Wrangler to see how “hackable” the deployment API was… and I found that it’s entirely possible to do deployments outside of the CLI tool. I prototyped my own deployment tool and created this high-level overview of the workflow:
- Get a Cloudflare Account ID, API Token & Pages Project Name (can be created/found in the Cloudflare dashboard)
- Create a list of all routes that the site will “serve”. Each item should have the following properties:
path
– The pathname of the file (include /index.html
for pages)contentType
– The mime type of the filebody
– A base64 encoded string of the file contentshash
– A hash of the(body + path)
from above using a hashing algorithm (I used MD5, Cloudflare uses blake3)length
– The length of the file in bytes (before base64 encoding)
- Create an upload JWT:
GET - v4/accounts/$accountId/pages/projects/$projectName/upload-token
- Include the API token in the header as described here.
- This token should be valid for 300 seconds (unless they change that expiration)
- Upload “buckets” with up to 50mb of files:
POST - v4/pages/assets/upload
- Use the upload token generated from the previous step (get a new token if it expired)
- The body will be a JSON array with each item having the following properties:
key
– File hashvalue
– Base64 file contentsmetadata
– Object with 1 property:contentType
– which will be the mime typebase64
–true
- Tell Cloudflare that new files were uploaded:
POST - v4/pages/assets/upsert-hashes
- Use the upload token from before
- The body is a JSON object with 1 property:
hashes
which is a string array with all of the new file hashes that were uploaded
- Create a deployment:
POST - v4/accounts/$accountId/pages/projects/$projectName/deployments
- Use the regular API token here and upload the body as
multipart/form-data
- The body is form data with 1 property:
manifest
– a JSON object with the following properties:[path]
– File hash
- This part is the most finicky, the server returns a 500 if the proper content disposition & boundaries aren’t set.
That’s it 😅.
There are a few other things that I glossed over like:
- Checking for hashes that are already uploaded
- Uploading custom redirects, headers, routes & Worker Functions
- Creating ‘branch’ deployments to preview changes
But this is would be a good starting point for any developer looking to integrate their project with Cloudflare Pages in a non-normal way. There are a lot of cool possibilities for integration here, like ISR (where only the files that changed are uploaded) & exposing an API layer with Worker Functions, etc. I ended up creating a WordPress plugin that automates this process as well as statically rendering the site (more on this in a later post).