| 1 | --- |
| 2 | title: 2.0.0-beta.40 - Vite Dev Server |
| 3 | date: 2026-05-15T22:00:00Z |
| 4 | category: release |
| 5 | excerpt: Cloudflare local dev gains a real Vite dev server (HMR, SSR, client + worker in one process), AiGateway stops reporting spurious updates on every deploy, the Worker HTTP server returns generic 500s while logging the full Cause server-side, and a handful of fixes around entrypoint generation, container startup, and the dev lockfile. |
| 6 | --- |
| 7 | |
| 8 | :::caution |
| 9 | **Upgrade immediately if you're on beta.39.** This release |
| 10 | reverts a critical bug introduced in beta.39 where |
| 11 | `scopeTransferToStream` caused **415** responses from |
| 12 | Workers and **500** errors against the Cloudflare state |
| 13 | store. The state store version has also been bumped to |
| 14 | **v5** — older clients will refuse to load mismatched |
| 15 | state and prompt you to upgrade. |
| 16 | ::: |
| 17 | |
| 18 | `v2.0.0-beta.40` is headlined by a real Vite dev server |
| 19 | for Cloudflare Workers — `Cloudflare.Website.Vite` now boots a |
| 20 | single process that serves your client, SSR, and Worker |
| 21 | through Vite, with HMR. The rest of the release is fixes |
| 22 | that quiet noisy diffs, tighten error responses, and |
| 23 | harden codegen against odd file paths. |
| 24 | |
| 25 | ## `Cloudflare.Website.Vite` — real Vite dev server |
| 26 | |
| 27 | `bun alchemy dev` for a `Cloudflare.Website.Vite` resource |
| 28 | previously bundled the Worker and served the built output |
| 29 | through the sidecar. That worked, but it skipped the part |
| 30 | of the Vite toolchain people actually want during |
| 31 | development: HMR, on-demand SSR, the client/SSR/worker |
| 32 | environments wired together. |
| 33 | |
| 34 | beta.40 replaces that with `vite.createServer` driven |
| 35 | through `@distilled.cloud/cloudflare-vite-plugin`. The |
| 36 | sidecar now hosts a Vite dev server that serves your |
| 37 | client and SSR, while the Worker runs in the same process |
| 38 | against the live module graph: |
| 39 | |
| 40 | ```typescript |
| 41 | const web = yield* Cloudflare.Website.Vite("Web", { |
| 42 | main: "./src/worker.ts", |
| 43 | env: { VITE_API_URL: api.url.as<string>() }, |
| 44 | }); |
| 45 | ``` |
| 46 | |
| 47 | - HMR works in dev — edit a route component, the browser |
| 48 | hot-reloads; edit the worker, the Worker reloads. |
| 49 | - `props.env` keeps the beta.39 semantics: `VITE_`-prefixed |
| 50 | keys are inlined into the client/SSR bundle via |
| 51 | `import.meta.env.*`, everything else is a runtime |
| 52 | Worker binding. |
| 53 | - Vite is resolved from the project's own `node_modules` |
| 54 | first (via `createRequire`) so you control the version. |
| 55 | |
| 56 | ## AiGateway: no more update-every-deploy |
| 57 | |
| 58 | `Cloudflare.AI.Gateway` was reporting `update` on every |
| 59 | `bun alchemy deploy`, even when nothing had changed. Two |
| 60 | things were going on: |
| 61 | |
| 62 | 1. The provider was diffing against `news` instead of |
| 63 | observed cloud state. |
| 64 | 2. The provider's defaults didn't match what the |
| 65 | Cloudflare API actually returns, so the first |
| 66 | post-create diff always showed drift. |
| 67 | |
| 68 | Both are fixed. Defaults now match the API's response |
| 69 | shape (`0`, `false`, `null` where the API returns those), |
| 70 | and `Diff.ts` gained the helpers needed to compare |
| 71 | observed-vs-desired correctly. Deploys are quiet again |
| 72 | unless something genuinely changed. |
| 73 | |
| 74 | Fixes [#332](https://github.com/alchemy-run/alchemy/issues/332) |
| 75 | and [#334](https://github.com/alchemy-run/alchemy/issues/334). |
| 76 | |
| 77 | ## Worker HTTP: log full Cause server-side, return generic 500 |
| 78 | |
| 79 | The Cloudflare Worker HTTP adapter was leaking internal |
| 80 | error detail into 500 responses. The fix flips that: the |
| 81 | full `Cause` (stack, annotations, defects) is logged on |
| 82 | the server, and the client receives a generic |
| 83 | `Internal Server Error` 500. Same behavior as Effect's |
| 84 | own `HttpServer.serve` defaults — just now consistent |
| 85 | under `Cloudflare.Worker`. |
| 86 | |
| 87 | This pairs with the beta.39 lifecycle adapter fix and |
| 88 | finishes the cleanup of the Worker HTTP path. |
| 89 | |
| 90 | Fixes [#336](https://github.com/alchemy-run/alchemy/pull/336). |
| 91 | |
| 92 | ## Sanitize entrypoint URLs in generated code |
| 93 | |
| 94 | Codegen for Lambda, ECS, EC2-hosted, Cloudflare Worker, |
| 95 | and Cloudflare Container entrypoints was interpolating |
| 96 | `importPath` directly into a template string: |
| 97 | |
| 98 | ```diff lang="typescript" |
| 99 | -import entrypoint from "${importPath}"; |
| 100 | +import entrypoint from ${JSON.stringify(importPath)}; |
| 101 | ``` |
| 102 | |
| 103 | On macOS/Linux this never bit anyone. On Windows, paths |
| 104 | containing backslashes (or any path with embedded quotes, |
| 105 | unicode, etc.) generated invalid TypeScript. `JSON.stringify` |
| 106 | emits a guaranteed-valid JS string literal across every |
| 107 | codegen site. |
| 108 | |
| 109 | ## Other fixes |
| 110 | |
| 111 | - **Cloudflare.start forwards startup options** — `start`'s |
| 112 | options were silently dropped before they reached the |
| 113 | container runtime. Thanks |
| 114 | **[Christopher Yovanovitch](https://github.com/yovanoc)** |
| 115 | ([#341](https://github.com/alchemy-run/alchemy/pull/341)). |
| 116 | - **`bun alchemy dev` lockfile** moves to |
| 117 | `@alchemy.run/node-utils` and the legacy `Sidecar/Lock.ts` |
| 118 | is gone ([#345](https://github.com/alchemy-run/alchemy/pull/345)). |
| 119 | - **Cloudflare state store version bumped to 5** — clients |
| 120 | pinned to older versions will refuse to load mismatched |
| 121 | state and prompt you to upgrade. |
| 122 | - **`scopeTransferToStream` reverted** — the optimization |
| 123 | was causing 415 responses under workerd; reverting |
| 124 | restores the previous (correct) HTTP semantics. |
| 125 | - **Axiom `smartfilter` chart subtype** — used by the |
| 126 | internal otel dashboard; available now if you build |
| 127 | your own Axiom charts via `Axiom.Chart` |
| 128 | ([#339](https://github.com/alchemy-run/alchemy/pull/339)). |
| 129 | |
| 130 | ## Contributors |
| 131 | |
| 132 | Big thank-you to everyone who shipped code in this beta: |
| 133 | |
| 134 | - **[Christopher Yovanovitch](https://github.com/yovanoc)** — `Cloudflare.start` options forwarding ([#341](https://github.com/alchemy-run/alchemy/pull/341)) |
| 135 | |
| 136 | ## Where to go next |
| 137 | |
| 138 | - [CHANGELOG](https://github.com/alchemy-run/alchemy/blob/main/CHANGELOG.md#v200-beta40) |
| 139 | - [Compare v2.0.0-beta.39 → v2.0.0-beta.40](https://github.com/alchemy-run/alchemy/compare/v2.0.0-beta.39...v2.0.0-beta.40) |