Cloudflare deploy
mx ships a Cloudflare deploy path as a conditional part of the folder
contract: a make/cloudflare.mk module and an infra/cloudflare/ tree that
exist only in projects that asked for them.
mx new my-app --infra cloudflare # at creation timemx infra setup cloudflare # credentials, once per workstationThe flow
Section titled “The flow”make cf-setup # interactive wizard: auth, account id, optional API tokenmake cf-init a=myapp type=worker # scaffold an app (worker | cron | container)make cf-deploy a=myapp # deploy to productionThree worker types, chosen at cf-init:
| Type | For |
|---|---|
worker | standard edge worker handling HTTP requests |
cron | scheduled worker, with KV for state and optional webhook notifications |
container | a container image behind a worker: port, sleep timeout, max instances, custom domain |
Target reference
Section titled “Target reference”| Target | Purpose |
|---|---|
make cf-setup | Interactive setup wizard |
make cf-vars | Show the resolved credentials and the scope they came from |
make cf-check-credentials | Fail early, with both paths named, when no account id resolves |
make cf-login / make cf-whoami | Authenticate / show auth status |
make cf-status / make cf-list | All apps’ status / list configured apps |
make cf-init a=<app> type=<type> | Initialize an app |
make cf-install a=<app> | Install worker dependencies |
make cf-dev a=<app> | Run the worker locally |
make cf-build a=<app> | Build the container image |
make cf-push a=<app> | Push to the Cloudflare registry |
make cf-publish a=<app> | Build and push |
make cf-images a=<app> | List registry images |
make cf-sync-image a=<app> | Sync wrangler.toml to a new image tag |
make cf-deploy a=<app> | Deploy to production |
make cf-deploy-preview a=<app> | Deploy to preview |
make cf-deploy-all | Deploy every configured app |
make cf-logs a=<app> / cf-logs-preview | Tail production / preview logs |
make cf-restart a=<app> | Restart the container |
make cf-container-status a=<app> | Check container status |
Per-app configuration lives in that app’s wrangler.toml. Credentials come from
mx infra or from make cf-setup, and both
are read: the environment first, then the project’s
infra/cloudflare/.env.cloudflare, then the global
~/.mech-crate/config/infra/cloudflare.env. One
mx infra setup cloudflare per workstation is enough, and make cf-setup is the
override for a project that deploys to a different account. make cf-vars prints
which scope answered; make cf-check-credentials fails loudly, naming both paths,
when none did.
The full guides
Section titled “The full guides”Worker type internals, directory layout, per-app wrangler.toml configuration,
versioning, CI/CD wiring and troubleshooting:
And a researched, as-implemented account of the same flow, including a drift inventory of the places the documentation and the code disagree. Worth reading before you debug a credential problem:
→ mx Cloudflare Deploy: as-implemented flow, credentials, and known traps
How this site ships
Section titled “How this site ships”mechcrate.dev is built from site/ in the mech-crate repository, a nested mx
project with the Astro app at site/apps/site/. The intended deploy is the
astro recipe’s Cloudflare path: a GitHub Actions workflow that runs astro build
on pushes to main touching site/** or docs/** and publishes the static
bundle with wrangler, plus a preview deploy on pull requests. The site job is
independent of the Rust gates. It never blocks ci.yml and is never blocked by
it.
That workflow is now .github/workflows/site.yml. site/ was scaffolded without
--infra cloudflare, so it has no make/cloudflare.mk. The workflow calls
wrangler directly rather than through the cf-* targets.
Two things about the dev container are specific to this site, and both are commented where they live:
- No database or cache. The astro recipe’s compose
includesdb.ymlandredis.yml; a static documentation build needs neither, sodocker/compose/site.ymldrops them. - The corpus lives outside the app. The techniques corpus is read from the
repository’s
docs/development/, which is aboveapps/siteand therefore outside the container’s source mount.docker/compose/site.dev.ymlbind-mountsdocs/read-only at/repo/docsand setsMECHCRATE_REPO_ROOT, somake devrenders the same 110 pages CI builds. Without it the site still comes up. It just silently loses all 67 corpus pages.
The production deploy does not use this container at all: CI runs astro build
and ships the static dist/ to Cloudflare.