DeployKit

Setup

Connect deploykit to Cloudflare Pages.

Install

Follow the installation guide to install the alpha packages, then configure the provider below.

Add credentials

In the Cloudflare dashboard, create an API token with the Cloudflare Pages: Edit permission, and copy your account id.

.env
CLOUDFLARE_API_TOKEN=...
CLOUDFLARE_ACCOUNT_ID=...

Create the client

src/deploykit.ts
import { Layer } from "effect"
import { NodeFileSystem } from "@effect/platform-node"
import * as Cloudflare from "@deploykit/cloudflare"

// Reads CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID from the environment.
export const DeploykitLive = Cloudflare.layerConfig().pipe(Layer.provide(NodeFileSystem.layer))

To pass options, use layer instead:

export const DeploykitLive = Cloudflare.layer({
  apiToken,
  accountId,
  previewBranch: "preview"
}).pipe(Layer.provide(NodeFileSystem.layer))

Client options

OptionDefaultWhat it does
apiTokenrequiredCloudflare API token
accountIdrequiredAccount that owns the projects
previewBranchnoneEnables preview deployments
retry{ attempts: 4 }Retries for reads and uploads
timeoutMs30000Time limit per HTTP operation, including retries
fetchglobal fetchCustom HTTP transport
memoryBudgetBytes, stagingBudgetBytes, maxFileBytessee LimitsShared memory and disk caps
onEventnoneTelemetry callback (Promise API). See Telemetry

What to deploy

The site's files at the root of the artifact, exactly as they should be served. This is what your framework puts in dist/ or build/:

index.html
about/index.html
assets/app.js
_worker.js       (optional, see Workers)
await deploykit.deployDirectory(appId, "./dist")

To run server code, add a _worker.js.

Pages' _headers, _redirects and _routes.json files aren't applied yet: they're uploaded as ordinary files. Set headers and redirects from your worker instead.

Deploy options

Pages supports the core options only. activation: "deferred", operationId and meta fail with UnsupportedError before anything is uploaded.

Preview deployments

Pages decides production versus preview by branch name. Set previewBranch on the client, then deploy with target: "preview":

const PreviewLive = Cloudflare.layer({
  apiToken,
  accountId,
  previewBranch: "preview"
})

const preview = Effect.gen(function* () {
  const deploykit = yield* Deploykit.Deploykit
  return yield* deploykit.deployDirectory(appId, "./dist", {
    target: "preview"
  })
})

The branch must differ from the project's production branch. Without previewBranch, target: "preview" is rejected, and capabilities.previewDeployments is false.

Limits

LimitValue
Static file25 MiB (Cloudflare's limit)
_worker.js8 MiB
Uploads at once4 per deploy

Files over 25 MiB fail with TransferLimitError before upload, whatever your budgets allow.

Not supported

FeatureWhat to do instead
Deferred activationEvery production deploy goes live when ready. Use a preview to check first
Recovering a lost responseCheck the project's deployments in Cloudflare before retrying
Access controlUse Cloudflare Access on the project's domain

A new project's first URL

A new project's *.pages.dev address can take 30 to 60 seconds to start resolving after its first deploy. Give waitUntilServing a generous timeoutMs, such as 120 seconds.

Separate coordinator and worker

@deploykit/cloudflare/control has no upload code and can be bundled for the browser or an edge runtime:

coordinator.ts
import { makeCloudflareClient, makeCloudflareControl } from "@deploykit/cloudflare/control"

const control = makeCloudflareControl(makeCloudflareClient({ apiToken, accountId }))
// control.createApp, getDeployment, ... all return Effects

Last updated on

On this page