Skip to content

Websites

GCP.Website deploys a frontend to Cloud Run. Each resource runs your framework’s build, bakes the server and the static files into one Node image, and serves it from a public Cloud Run service. There is no Dockerfile and no adapter to install. Your framework’s own config file loads as-is.

alchemy.run.ts
import * as Alchemy from "alchemy";
import * as GCP from "@alchemy.run/gcp";
import * as Effect from "effect/Effect";
export default Alchemy.Stack(
"MySite",
{ providers: GCP.providers(), state: GCP.state() },
Effect.gen(function* () {
const site = yield* GCP.Website.Astro("Website");
return { url: site.url };
}),
);

site.url is the service’s https://….run.app URL.

The build integration ships separately. It only runs at deploy time, so a dev dependency is enough:

Terminal window
pnpm add -D @alchemy.run/frontend-frameworks@latest

Docker has to be running when you deploy. The image is built on your machine.

Framework Resource Guide
React / Vite SPA Vite React SPA
Vue Vite Vue
Any Vite app Vite Vite
Foldkit Foldkit Foldkit
Astro Astro Astro
Next.js Nextjs Next.js
vinext Vinext vinext
Nuxt Nuxt Nuxt
SvelteKit SvelteKit SvelteKit
TanStack Start TanStackStart TanStack Start
React Router ReactRouter React Router
SolidStart SolidStart SolidStart
Waku Waku Waku
Octane Octane Octane
Vocs Vocs Vocs
Hugo, Zola, any static generator StaticSite Static sites

Use the resource named after your framework. Use Vite for a client-only app. Use StaticSite for any build command that writes a directory of files.

env sets the server’s environment. Values can be Outputs from other resources:

const site = yield* GCP.Website.Nuxt("Website", {
env: {
GREETING: "Hello from Cloud Run!",
API_URL: api.uri,
},
});

Server code reads them from process.env.

Every site takes the same Cloud Run settings:

const site = yield* GCP.Website.Nextjs("Website", {
scaling: { minInstanceCount: 1 },
resources: { limits: { cpu: "1", memory: "1Gi" } },
timeout: "60s",
});

minInstanceCount: 1 keeps one instance warm, so the first visitor never waits for a cold start.

Sites are public by default. Set public: false to require a Google identity token, for an internal tool behind IAP or a load balancer:

const site = yield* GCP.Website.Vite("Admin", { public: false });

Alchemy hashes your project’s files and skips the build and the image push when nothing changed. Limit the hash to the files that matter:

const site = yield* GCP.Website.Astro("Website", {
memo: {
include: ["src/**", "public/**", "package.json", "astro.config.ts"],
},
});

alchemy dev runs your framework’s own dev server with hot reload and creates nothing in the cloud. site.url is the local address. Wrap the site in Alchemy.remote() to deploy it for real during dev.