Skip to content
Launch
Esc
↑↓navigate↵open⌘Jpreview
On this page

Deploying to Workers

Every app in Launch deploys as a Cloudflare Worker with the cf CLI, configured in cloudflare.config.ts, with no Wrangler config in the repo.

Every front-end, the MCP server and this site are each their own Cloudflare Worker. The two WordPress installs run on a WordPress host instead; see Deploying WordPress. None of the Workers has a wrangler.jsonc, wrangler.toml or a Wrangler dependency; those file names are gitignored. Workers, bindings, secrets and Access applications are created through the cf CLI and the Cloudflare API, by scripts in each app.

The pattern

  1. cloudflare.config.ts holds the Worker’s name, compatibility date, domains and bindings. It is the cf CLI’s typed config, not a Wrangler file. The account comes from CLOUDFLARE_ACCOUNT_ID, never from the file.
  2. Secrets are declared by name with bindings.secret(). Values come from the shell at deploy time and from a gitignored .env.local locally, and are never written to a file in the repo.
  3. The build writes Cloudflare Build Output to .cloudflare/output/. The vinext apps get it from the Cloudflare Vite plugin.
  4. pnpm run deploy uploads that output with cf deploy --prebuilt, which creates the Worker on its first run and provisions any binding resources, such as a KV namespace, that do not exist yet. pnpm run deploy --preview runs cf previews deploy --prebuilt instead, which names a Worker Preview after the Git branch.
  5. Workers Builds runs those commands on every push. There are no GitHub Actions. See Workers Builds.
pnpm --filter web-wordpress run deploy             # production
pnpm --filter web-wordpress run deploy --preview   # a Preview named after the branch
pnpm --filter web-wordpress run deploy --dry-run   # build and check, upload nothing

Locally, sign in with cf auth login, or set CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID.

Custom domains

Set WORKER_DOMAIN when building and the next production deploy attaches it as the Worker’s custom domain. The zone must be on the same account. WORKER_DOMAIN_PREVIEWS=true also serves each Preview at <preview>.<domain>; those hostnames are two levels below the zone, which a Free plan’s Universal SSL certificate does not cover, so it is off by default. Previews always get a workers.dev URL.

This docs site

The docs site is a static Blume build, deployed the same way as an assets-only Worker: no Worker code, no bindings and no secrets. Blume drives its own Astro build rather than Vite’s Cloudflare plugin, so scripts/build-output.mjs writes the Build Output from dist/ with the same libraries the cf CLI uses, and the deploy then runs cf deploy --prebuilt like every other app.

pnpm --filter docs-site run deploy --dry-run

htmlHandling is drop-trailing-slash, because Blume links to each page without a trailing slash.

Was this page helpful?