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.htmlfor 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:
hasheswhich 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).
