Vite
Cloudflare.Website.Vite deploys any app that is pure Vite — a
project whose entire build is vite build with plugins from your
vite.config.ts. That covers a plain index.html, a React or Vue
SPA, and full-stack SSR frameworks like TanStack Start or React
Router. This page explains the resource itself; each supported
framework has its own landing page that flows from
here.
One resource, one build
Section titled “One resource, one build”The minimal form takes no props at all:
const site = yield* Cloudflare.Website.Vite("Website");Alchemy loads your project’s Vite install (resolved from
rootDir’s package.json), appends the Cloudflare Vite plugin —
Alchemy’s fork of @cloudflare/vite-plugin — to the plugins your
vite.config.ts already declares, and runs builder.buildApp().
Client assets are uploaded as Worker static assets; if the build
emits a server bundle (SSR), that bundle becomes the Worker entry —
otherwise the Worker is assets-only. There is no main entrypoint,
no build command, no output directory, and no wrangler.jsonc: an
index.html next to your alchemy.run.ts (plus your
vite.config.ts, if you have one) is enough.
What pure Vite means
Section titled “What pure Vite means”Condensed from the provider, a deploy runs exactly this:
const vite = await loadVite(rootDir); // your project's own vite installconst builder = await vite.createBuilder({ root: rootDir, define: getDefine(env), // VITE_-prefixed env, see Environment below plugins: [cloudflare(pluginOptions), outputPlugin.plugin],}, null);await builder.buildApp();A framework is supported if — and only if — a vite build of your
vite.config.ts builds the whole app. Frameworks whose build is
orchestrated by their own CLI (astro build, nuxi build) never
enter this path, so they are not yet supported by this resource —
see Astro and
Nuxt for their current status and
workarounds, or StaticSite as
the general fallback for any build command that produces a
directory of files.
Remove @cloudflare/vite-plugin
Section titled “Remove @cloudflare/vite-plugin”ViteProps is WorkerProps minus the things the build now owns
(main, the directory-shaped assets), plus Vite-specific options:
const site = yield* Cloudflare.Website.Vite("Website", { rootDir: "./web", compatibility: { flags: ["nodejs_compat"] }, assets: { runWorkerFirst: true },});rootDir— Vite’s project root, defaultprocess.cwd().memo— narrows which files are hashed to decide whether a rebuild is needed (see Rebuilds and memo).viteEnvironments— for frameworks that build more than one server environment (see Multiple server environments).assets— a flatAssetsConfigfor routing behavior:runWorkerFirst,htmlHandling,notFoundHandling, etc. The built asset directory is supplied by the build, so unlike a plain Worker there is nodirectoryto configure.- Everything else is inherited from the Worker —
domain,env,compatibility,crons, and so on. See Workers.
Like Worker, the resource also has a class form — useful when
other resources bind to the site, or when you want to derive its
env types:
export class Website extends Cloudflare.Website.Vite<Website>()("Website", { compatibility: { flags: ["nodejs_compat"] },}) {}See TanStack Start for the class form in a real app.
Environment
Section titled “Environment”env feeds your app through two distinct channels: build-time
inlining into the client bundle, and runtime Worker bindings for
server code.
Build-time inlining
Section titled “Build-time inlining”Only VITE_-prefixed keys are inlined into the client bundle as
import.meta.env.<KEY>, matching vite build’s default
envPrefix semantics:
const web = yield* Cloudflare.Website.Vite("Website", { env: { VITE_API_URL: backend.url.as<string>(), },});Output values like backend.url resolve at deploy time before
the build runs, so the client reads a concrete
import.meta.env.VITE_API_URL. Redacted values are unwrapped
when VITE_-prefixed — the prefix means you are opting the value
into the public bundle, so don’t prefix secrets with VITE_.
Runtime bindings
Section titled “Runtime bindings”Non-VITE_ values become native Worker bindings, available to SSR
code and typed via Cloudflare.InferEnv:
export class Website extends Cloudflare.Website.Vite<Website>()("Website", { compatibility: { flags: ["nodejs_compat"] }, env: { BUCKET: Bucket, BACKEND: Backend, },}) {}
export type WebsiteEnv = Cloudflare.InferEnv<typeof Website>;See TanStack Start for the full pattern of consuming these bindings from server routes.
Multiple server environments (RSC)
Section titled “Multiple server environments (RSC)”viteEnvironments defaults to { entry: "ssr", children: [] }.
Frameworks that emit several server environments — React Server
Components split into rsc and ssr — declare which environment
produces the Worker entry chunk and which are bundled alongside it:
const app = yield* Cloudflare.Website.Vite("ReactRouterRSC", { compatibility: { flags: ["nodejs_compat"] }, viteEnvironments: { entry: "rsc", children: ["ssr"] },});The entry environment becomes the deployed Worker entry,
children chunks are bundled alongside it, and the client
environment is always deployed as static assets. See
React Router for the worked
example.
Rebuilds and memo
Section titled “Rebuilds and memo”By default, every non-gitignored file under rootDir plus the
nearest lockfile is content-hashed; if nothing changed, both the
build and the deploy are skipped entirely. The hash is
path-insensitive — relocating rootDir with identical sources is a
no-op deploy. Narrow the scope with memo when the project
contains large directories that don’t affect the build output:
const site = yield* Cloudflare.Website.Vite("Docs", { memo: { include: ["src/**", "index.html", "package.json"], },});Local dev
Section titled “Local dev”bun alchemy devalchemy dev boots Vite’s own dev server programmatically with the
Cloudflare plugin attached — you get HMR on your application code
while bindings point at the real cloud resources, so there is
no emulation fidelity gap. By default the dev server picks an
available port; set dev.port to keep the local URL stable across
runs:
const web = yield* Cloudflare.Website.Vite("Website", { dev: { port: 3000 },});Frameworks
Section titled “Frameworks”Each supported framework has its own landing page building on this resource:
- React SPA — single-page apps,
from a bare
index.htmlto thecreate-vitetemplate. - TanStack Start — full-stack React and Solid with server routes and typed bindings.
- React Router — including
React Server Components via
viteEnvironments. - Vue — Vue 3 SPAs.
- SolidStart — SolidStart and hand-rolled SolidJS SSR.
Not yet supported by this resource: Astro
and Nuxt — their builds are driven by
their own CLIs, not vite build. Their pages document the current
workarounds, generally deploying build output with
StaticSite.