The answer. C3 (npm create cloudflare@latest) scaffolds the project and writes the config; Wrangler does everything after that. wrangler dev runs the Worker locally in workerd on port 8787 with local simulations of every binding. wrangler deploy uploads the bundle, creates the workers.dev route, provisions DNS and TLS, and prints the URL and a version id. wrangler tail streams live logs. The only interactive step is the first wrangler login, which opens a browser and stores an OAuth token on your machine; CI uses an API token instead.
The pattern.
npm create cloudflare@latest my-api -- --type=hello-world --ts --git # 1. scaffold
cd my-api && npx wrangler dev # 2. local, http://localhost:8787
curl -s http://localhost:8787/ # 3. exercise it
npx wrangler deploy # 4. first run opens the login page
npx wrangler tail # 5. live logs from the edge
Uploaded my-api (1.2 sec)
Deployed my-api triggers (0.8 sec)
https://my-api.<your-subdomain>.workers.dev
Current Version ID: 0f3c... <- keep this; it is what you roll back to
Watch out.
- The
workers.devhostname is public the moment you deploy. Setworkers_dev = falseonce a custom domain exists, or put Access in front of it. compatibility_dateis generated at scaffold time and pinned forever. Bumping it is a deliberate change, not a chore.wrangler deploywith no--envdeploys the top-level config. Name the top-level Worker something that can never be production.
Related: what-a-worker-is-fetch-handler-plus-bindings · wrangler-dev-local-by-default-remote-bindings · deploy-with-rollback-target-health-probe