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:
- 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.)
- Locally preview what the full public website will look like, before committing & pushing a completed post out to the web.
- 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:
- 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.
- 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.
- Each item in the site hierarchy (post or page) has, in its Markdown front matter, a
status
. This will be one ofpublished
,draft
orhidden
.
- The blog's Publish pipeline has two build targets,
Staging
andPublic
:
Public
includes only items with thepublished
status.Staging
includes items having eitherpublished
ordraft
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:
- Log in to your Cloudflare account
- Select Pages in the sidebar
- Select Create a Project, then Connect GitHub
- 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.
- Select Only select repositiories; pick the build submodule repository
- Login to GitHub
Perform actual Pages deployment setup:
- Deploy site from your account: confirm GitHub account and repository, select Begin setup.
- 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
- 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!