Recently was asked how to redirect URLs from Substack to Ghost.

It turns out that this is a great use case for Cloudflare serverless workers.

So much so that there is a script along with instructions for doing bulk redirects using Cloudflare workers available on the Cloudflare website.

Whilst working through this discovered a couple of gotchas.

In the example on the Cloudflare website it expects that the incoming path name will contain /redirect.

Following is an example with the path changed:

const externalHostname = ""

const redirectMap = new Map([
  ["/p/bulk1", "https://" + externalHostname + "/redirect2"],
  ["/p/bulk2", "https://" + externalHostname + "/redirect3"],
  ["/p/bulk3", "https://" + externalHostname + "/redirect4"],
  ["/p/bulk4", ""],

async function handleRequest(request) {
  const requestURL = new URL(request.url)
  const path = requestURL.pathname
  const location = redirectMap.get(path)
  if (location) {
    return Response.redirect(location, 301)
  // If request not in map
  return Response.redirect("https://"+externalHostname, 301)

addEventListener("fetch", async event => {

The other gotcha had to do with Substack taking ownership of the URL to utilise the Cloudflare's SSL for SaaS add-on which caused the worker not to be available on the route. If you experience this, a request to Cloudflare support is required to remove what they call a "custom hostname".

To test if your URL is has a custom hostname use the following:

curl -I [replace-with-your-URL]
HTTP/2 200
x-cluster: substack

To read more about Cloudflare workers visit what is a Cloudflare worker you might ask.

Share a comment with any suggestions.

Let's continue the conversation.