27 December 2021

27 December 2021, 12:02 (Published)

Deploying a Swift Publish website on Cloudflare Pages

Fast, free and furious 🚀

This blog is a static Swift Publish website, deployed at Cloudflare pages via a GitHub repository.

Cloudflare Pages' getting started documentation explains nicely how this works, if you're using one of the more popular static website generators that Cloudflare can run on demand to build the website from sources.

While Publish isn't among Cloudflare's supported website generators, it also works just fine to build the site locally on your Mac, and only have Cloudflare Pages serve the pre-built static website to the world.

In fact, thanks to the flexibility of being able to tweak Publish itself to my particular needs, this blog has a specific, customised publishing workflow that feels just right (to me.)

This post is about how I put this together, with the ability to:

  1. Continuously preview a staging version of the full website, locally on the Mac, while writing new posts. (At this stage, any particular post may remain in an unpublishable draft state for quite a while, and frequent previewing in final, rendered form is part of the process.)
  1. Locally preview what the full public website will look like, before committing & pushing a completed post out to the web.
  1. Publish a static snapshot of the blog from the command line, by pushing a commit to the main branch of a GitHub repository.

This is all relatively easy to achieve with Publish and Cloudflare Pages, but takes a bit of thinking and tinkering.

Overview of Cloudflare setup

Cloudflare Pages provides functionality well beyond what this particular blog is ever going to make full use of. For example, it supports preview deployments before updating the production website, which I bet is great for a team of multiple contributors.

Being a solo writer-tinkerer, however, I find local previewing preferable. With this in mind, from Cloudflare's perspective, this is all there is to this blog:

  1. A GitHub repository that contains only the directory hierarchy of a static website, pre-built using Publish on the Mac where I did the writing.
  1. Deployment setup that tracks this GitHub repository, and deploys any commits to its main branch.

Before going through the Cloudflare deployment configuration, let's jump over to the Publish side for a bit.

Overview of Publish setup

For this particular website, I chose to customise the default Publish process in the following ways.

  1. Each item in the site hierarchy (post or page) has, in its Markdown front matter, a status. This will be one of published, draft or hidden.
  1. The blog's Publish pipeline has two build targets, Staging and Public:
  • Public includes only items with the published status.
  • Staging includes items having either published or draft as the status.
  • Neither target includes hidden items.

In practice, I use item status like this:

A vague idea for a post, to maybe get back to sometime in the future, gets the hidden status, and won't clutter even the local staging build of the blog. An idea that ultimately doesn't pan out, may get demoted down to hidden as well.

A strong candidate for a post, that I actually plan to complete soon, starts in the draft status, and does show up in the local staging build of the blog.

A finished post gets promoted to published — and the entire site re-deployed vi…git push origin main`.

Finally, any and all items must have one of the three statuses set. For this, there is a validation build step that fails the Publish build, if either the status field is missing from an item's front matter, or the value is unknown.

Publish customisations

The details of implementing item statuses and build targets on Publish get fiddly enough to warrant a separate post.

Deployment

To get going initially, start by giving Cloudflare just the right access to the GitHub repository:

  1. Log in to your Cloudflare account
  2. Select Pages in the sidebar
  3. Select Create a Project, then Connect GitHub
  4. Pick GitHub account to authorise. You will have multiple to choose from if, for example, you belong to GitHub organisation for the day job, and tinker using a personal account.
  5. Select Only select repositiories; pick the build submodule repository
  6. Login to GitHub

Perform actual Pages deployment setup:

  1. Deploy site from your account: confirm GitHub account and repository, select Begin setup.
  1. Set up builds and deployments:
  • Edit Project name (the default will be the name of the Git repository.) This will get applies as .pages.dev subdomain.
  • Pick Production branch (default will be main)
  • Keep Framework preset at None
  • Set Build command to: exit 0
  • Set Build output directory (the default is /, in my case I set this to Public)
  • Root directory (advanced) and Environment variables (advances) need no changes
  • Click Save and Deploy
  1. Building and deploying:
  • Watching the deployment progress for the very first time, the Initializing build environment step took roughly two and a half minutes. This, fairly enough, is printed out at the very beginning of the deployment log.
  • The deployment log hints at what takes so long with the initialization: you have a lot of stuff available, presumably for Cloudflare workers.
12:34:46.823	Initializing build environment. This may take up to a few minutes to complete
12:37:25.334	Success: Finished initializing build environment
12:37:25.334	Cloning repository...
12:37:27.843	Success: Finished cloning repository files
12:37:28.134	Installing dependencies
12:37:28.137	Python version set to 2.7
12:37:29.520	v12.18.0 is already installed.
12:37:30.122	Now using node v12.18.0 (npm v6.14.4)
12:37:30.174	Started restoring cached build plugins
12:37:30.179	Finished restoring cached build plugins
12:37:30.338	Attempting ruby version 2.7.1, read from environment
12:37:31.540	Using ruby version 2.7.1
12:37:31.846	Using PHP version 5.6
12:37:31.883	5.2 is already installed.
12:37:31.890	Using Swift version 5.2
12:37:31.890	Installing Hugo 0.54.0
12:37:40.811	Hugo Static Site Generator v0.54.0-B1A82C61A/extended linux/amd64 BuildDate: 2019-02-01T10:04:38Z
12:37:40.812	Started restoring cached go cache
12:37:40.816	Finished restoring cached go cache
12:37:40.846	go version go1.14.4 linux/amd64
12:37:40.852	go version go1.14.4 linux/amd64
12:37:40.853	Installing missing commands
12:37:40.853	Verify run directory
12:37:40.853	Executing user command: exit 0
12:37:40.854	Finished
12:37:40.855	Note: No functions dir at /functions found. Skipping.
12:37:40.855	Validating asset output directory
12:37:41.196	Deploying your site to Cloudflare's global network...
12:37:46.205	Success: Your site was deployed!