Skip to content

Astro

Astro’s static output is just a directory of files, and Cloudflare.Website.StaticSite deploys any directory produced by any build command. This isn’t a theoretical workaround: the Alchemy docs site itself (alchemy.run) is an Astro/Starlight app deployed exactly this way.

alchemy.run.ts
import * as Alchemy from "alchemy";
import * as Cloudflare from "alchemy/Cloudflare";
import * as Effect from "effect/Effect";
export default Alchemy.Stack(
"MyAstroSite",
{
providers: Cloudflare.providers(),
state: Cloudflare.state(),
},
Effect.gen(function* () {
const site = yield* Cloudflare.Website.StaticSite("Website", {
command: "astro build",
outdir: "dist",
compatibility: {
flags: ["nodejs_compat"],
},
});
return { url: site.url };
}),
);

StaticSite runs astro build as a shell command, content-hashes the dist directory, and deploys it as a Worker serving static assets — the docs site’s own declaration is the same shape, except its command is bun run build (which ends in astro build).

Optionally, a custom Worker can run before asset serving — set main and runWorkerFirst:

const site = yield* Cloudflare.Website.StaticSite("Website", {
command: "astro build",
main: "./src/worker.ts",
outdir: "dist",
compatibility: {
flags: ["nodejs_compat"],
},
assets: {
runWorkerFirst: true,
},
});

The docs site uses this to rewrite OG and canonical tags with HTMLRewriter (so preview deployments unfurl themselves instead of production) and to serve 301 redirects — see a custom Worker in front of your assets for the full pattern.

This path deploys Astro’s static output only. Astro SSR — output: "server" with the Cloudflare adapter — is not verified with Alchemy, so server-rendered routes, Astro actions, and middleware won’t run; everything must be rendered at build time.

For alchemy dev, use StaticSite’s standard external dev-server mechanism — dev.command spawns the framework’s own dev server instead of running the build:

const site = yield* Cloudflare.Website.StaticSite("Website", {
command: "astro build",
dev: {
command: "astro dev",
},
outdir: "dist",
});

This is the same mechanism StaticSite uses for any framework’s dev server (the docs site doesn’t set dev.command, so treat the astro dev pairing as the standard recipe rather than a battle-tested one) — see StaticSite for how external dev mode works.

Astro support in the Vite resource is tracked as a TODO; until it lands, the matrix on Frontend frameworks reflects current status.