1---
2title: "Part 4: Local Dev"
3description: Run your stack locally with alchemy dev for hot reloading and instant feedback.
4sidebar:
5 order: 4
6---
7
8In [Part 3](/cloudflare/tutorial/part-3) you wrote integration tests against
9your deployed stack. But deploying to Cloudflare on every code change
10is slow. In this part you'll use `bun alchemy dev` to run everything
11locally with hot reloading.
12
13## Start dev mode
14
15```sh
16bun alchemy dev
17```
18
19That's it. Alchemy deploys your stack to the cloud and proxies
20requests to Workers running locally in workerd. It watches for file
21changes and hot reloads your Worker automatically.
22
23Your Worker is available at `http://localhost:1337` by default:
24
25```sh
26curl http://localhost:1337/hello.txt
27```
28
29## How it works
30
31`bun alchemy dev` does three things:
32
331. **Deploys to the cloud** — resources like R2 Buckets are created
34 on Cloudflare, while Workers run locally in workerd
352. **Watches for changes** — when you edit `src/worker.ts` or any
36 file it imports, the Worker is rebuilt and reloaded instantly
373. **Preserves local state** — data in your local R2 Bucket persists
38 across restarts
39
40The same `alchemy.run.ts` is used for both `dev` and `deploy` — no
41separate dev config needed.
42
43## Custom port
44
45Set a custom port for your Worker:
46
47```diff lang="typescript"
48// src/worker.ts
49export default Cloudflare.Worker(
50 "Worker",
51 {
52 main: import.meta.url,
53+ dev: {
54+ port: 3000,
55+ },
56 },
57 // ...
58);
59```
60
61## Run tests in dev mode
62
63You don't need to run `bun alchemy dev` in a separate terminal to test
64against locally-emulated resources. The test harness has its own
65`dev` flag that flips every Worker over to workerd inside the test
66process — same wiring as `bun alchemy dev`, no extra terminal.
67
68```diff lang="typescript"
69// test/integ.test.ts
70const { test, beforeAll, afterAll, deploy, destroy } = Test.make({
71 providers: Cloudflare.providers(),
72 state: Cloudflare.state(),
73+ dev: true,
74});
75```
76
77`beforeAll(deploy(Stack))` now boots the Workers locally; HTTP
78assertions hit `http://localhost:1337` and roundtrip into your code
79with full stack traces.
80
81## Toggle dev mode from CI
82
83Hardcoding `dev: true` would force CI runs to local emulation too.
84Read it from the environment instead so the same test file runs
85against real cloud resources in CI and locally-emulated ones on your
86laptop.
87
88```diff lang="typescript"
89const { test, beforeAll, afterAll, deploy, destroy } = Test.make({
90 providers: Cloudflare.providers(),
91 state: Cloudflare.state(),
92- dev: true,
93});
94```
95
96Drop the explicit flag and the harness falls back to the
97`ALCHEMY_DEV` env var — set `ALCHEMY_DEV=1` in your shell to flip
98to local mode, leave it unset in CI.
99
100```sh
101ALCHEMY_DEV=1 bun test test/integ.test.ts
102```
103
104## Recap
105
106You now have:
107
108- Local development with `bun alchemy dev`
109- Hot reloading on file changes
110- Local emulation of Cloudflare resources
111
112In [Part 5](/cloudflare/tutorial/part-5), you'll set up GitHub Actions for
113automated deployments and PR preview environments.