Skip to content

GCP.Website reference

Source: src/GCP/Website/Astro.ts

Deploy an Astro application to Cloud Run: a service running the Node adapter’s serve entry (static files first, then the framework handler) on Cloud Run’s PORT (8080).

Pages render on demand by default (output: "server"). With astro: { output: "static" } every page is prerendered and the deploy is assets-only.

Basic Astro App

const site = yield* GCP.Website.Astro("Web", {
rootDir: "./app",
});

Warm Instance with More Memory

const site = yield* GCP.Website.Astro("Web", {
rootDir: "./app",
scaling: { minInstanceCount: 1 },
resources: { limits: { cpu: "1", memory: "1Gi" } },
});
const site = yield* GCP.Website.Astro("Docs", {
rootDir: "./docs",
astro: { output: "static" },
assets: { notFoundHandling: "404-page" },
});

Source: src/GCP/Website/Foldkit.ts

Deploy a Foldkit app to Cloud Run. Foldkit apps are client-only Vite projects, so this is Vite with SPA fallback to index.html so deep links boot the app.

Foldkit app

const site = yield* GCP.Website.Foldkit("Web");

Project in a subdirectory

const site = yield* GCP.Website.Foldkit("Web", {
rootDir: "applications/web",
});
const site = yield* GCP.Website.Foldkit("Web", {
assets: { notFoundHandling: "404-page" },
});

Source: src/GCP/Website/Nextjs.ts

Deploy a Next.js application to Cloud Run as a long-running Node process: next build, then a serve entry that import("next") + next({ dev: false }).prepare() + getRequestHandler(). The .next output (and public/ when present) is baked into the image; next is installed unbundled.

Do not use OpenNext AWS/CF wrappers — those are Lambda/workerd.

During alchemy dev the site is next dev and no cloud resources are declared; Alchemy.remote() opts back into the live Cloud Run service.

Basic Next.js App

const site = yield* GCP.Website.Nextjs("Web", {
rootDir: "./app",
});

Warm Instance with More Memory

const site = yield* GCP.Website.Nextjs("Web", {
rootDir: "./app",
scaling: { minInstanceCount: 1 },
resources: { limits: { cpu: "1", memory: "1Gi" } },
});

Source: src/GCP/Website/Nuxt.ts

Deploy a Nuxt application to Cloud Run: the nitro Node server in a Cloud Run container, static assets (prerendered pages included) baked into the image.

Basic Nuxt App

const site = yield* GCP.Website.Nuxt("Web", {
rootDir: "./app",
});

Warm Instance with More Memory

const site = yield* GCP.Website.Nuxt("Web", {
rootDir: "./app",
scaling: { minInstanceCount: 1 },
resources: { limits: { cpu: "1", memory: "1Gi" } },
});

Source: src/GCP/Website/Octane.ts

Deploy an OctaneJS application to Cloud Run: Octane’s SSR server in a Cloud Run container, static assets baked into the image.

GCP.Website.Octane selects hosting and automatically wraps Octane’s default native Node output. Keep compiler and route settings in octane.config.ts without an adapter. The legacy Node marker adapter remains optional for existing projects.

Basic Octane App

const site = yield* GCP.Website.Octane("Web", {
rootDir: "./app",
});

Warm Instance with More Memory

const site = yield* GCP.Website.Octane("Web", {
rootDir: "./app",
scaling: { minInstanceCount: 1 },
resources: { limits: { cpu: "1", memory: "1Gi" } },
});

Source: src/GCP/Website/ReactRouter.ts

Deploy a React Router v7 app (framework mode) to Cloud Run: the SSR server in a Cloud Run container, static assets baked into the image, served assets-first then the framework handler.

The build runs through @alchemy.run/frontend-frameworks/react-router with the @alchemy.run/frontend-frameworks/react-router/node deploy target — both must be installed in your project, alongside @react-router/dev, react-router, and vite.

Your vite.config.ts needs no adapter wiring. React Router’s server build is a ServerBuild manifest rather than a request handler, so the integration wraps the manifest with createRequestHandler and packages the resulting fetch handler as a Node HTTP server on Cloud Run’s PORT (8080).

React Server Components (React Router’s unstable RSC plugin) and multi-environment builds are not supported yet — the build fails with an actionable error when more than one server entry is emitted.

Basic React Router App

const site = yield* GCP.Website.ReactRouter("Web", {
rootDir: "./app",
});

Warm Instance with More Memory

const site = yield* GCP.Website.ReactRouter("Web", {
rootDir: "./app",
scaling: { minInstanceCount: 1 },
resources: { limits: { cpu: "1", memory: "1Gi" } },
});

Process Environment

const site = yield* GCP.Website.ReactRouter("Web", {
rootDir: "./app",
env: {
GREETING: "Hello from React Router on Cloud Run!",
},
});

Read An Environment Variable From A Loader

app/routes/home.tsx
export function loader() {
return { greeting: process.env.GREETING ?? "Hello!" };
}

Source: src/GCP/Website/SolidStart.ts

Deploy a SolidStart application to Cloud Run: the SSR server in a Cloud Run container, static assets (prerendered pages included) baked into the image, served assets-first then the framework handler.

The build runs through @alchemy.run/frontend-frameworks/solidstart with the @alchemy.run/frontend-frameworks/solidstart/node deploy target — both must be installed in your project, alongside @solidjs/start and @solidjs/vite-plugin-nitro-2.

Your vite.config.ts needs no adapter wiring: the integration drives the project’s own vite build and appends its own nitro plugin instance carrying nitro’s node preset.

Basic SolidStart App

const site = yield* GCP.Website.SolidStart("Web", {
rootDir: "./app",
});

Warm Instance with More Memory

const site = yield* GCP.Website.SolidStart("Web", {
rootDir: "./app",
scaling: { minInstanceCount: 1 },
resources: { limits: { cpu: "1", memory: "1Gi" } },
});
const site = yield* GCP.Website.SolidStart("Web", {
rootDir: "./app",
env: {
GREETING: "Hello from SolidStart on Cloud Run!",
},
});

The integration owns the nitro plugin instance (a nitroV2Plugin() in your vite.config.* is rejected), so nitro options — prerendering included — go on the nitro prop. Prerendered pages are baked into the image and served as static files.

const site = yield* GCP.Website.SolidStart("Web", {
rootDir: "./app",
nitro: { prerender: { routes: ["/", "/about"] } },
});

Source: src/GCP/Website/StaticSite.ts

Deploy a static site built by a shell command to Cloud Run.

StaticSite runs a build command (e.g. npm run build / hugo), content-hashes the output directory, and deploys a Cloud Run service whose image is a tiny Node file server over those files (plus /health). Use this when the site has its own build step — Hugo, Zola, Eleventy, or any custom pipeline.

For Vite-based projects, prefer GCP.Website.Vite. For a bucket-backed site behind a CDN, compose GCP.Storage.Bucket with a load balancer instead (see the gcp-static-site example).

Build / Dev use constant logical ids under Namespace.push(id). The Cloud Run service stays in the caller namespace.

Deploying a Hugo site

const site = yield* GCP.Website.StaticSite("Blog", {
build: { command: "hugo --minify", output: "public" },
});

SPA-style routing

const site = yield* GCP.Website.StaticSite("App", {
build: { command: "npm run build", output: "dist" },
assets: { notFoundHandling: "single-page-application" },
});
const site = yield* GCP.Website.StaticSite("Web", {
path: "apps/web",
build: { command: "npm run build", output: "dist" },
});
const site = yield* GCP.Website.StaticSite("Internal", {
build: { command: "npm run build", output: "dist" },
public: false,
scaling: { minInstanceCount: 1 },
});
const site = yield* GCP.Website.StaticSite("App", {
build: { command: "npm run build", output: "dist" },
dev: { command: "npm run dev" },
});

Source: src/GCP/Website/SvelteKit.ts

Deploy a SvelteKit application to Cloud Run: kit’s SSR server in a Cloud Run container, static assets baked into the image, served assets-first then the framework handler.

Basic SvelteKit App

const site = yield* GCP.Website.SvelteKit("Web", {
rootDir: "./app",
});

Warm Instance with More Memory

const site = yield* GCP.Website.SvelteKit("Web", {
rootDir: "./app",
scaling: { minInstanceCount: 1 },
resources: { limits: { cpu: "1", memory: "1Gi" } },
});

Source: src/GCP/Website/TanStackStart.ts

Deploy a TanStack Start application to Cloud Run: the SSR server in a Cloud Run container, client assets baked into the image, served assets-first then the framework handler.

The build runs through @alchemy.run/frontend-frameworks/tanstack-start with the @alchemy.run/frontend-frameworks/tanstack-start/node deploy target — both must be installed in your project, alongside @tanstack/react-start (or @tanstack/solid-start) and vite.

Your vite.config.ts needs no adapter wiring: TanStack Start is pure Vite, so the integration drives the project’s own vite build, forces the SSR bundle to be self-contained, and wraps its fetch handler as a Node HTTP server on Cloud Run’s PORT (8080).

TanStackStart: Creating TanStack Start Sites

Section titled “TanStackStart: Creating TanStack Start Sites”

Basic TanStack Start App

const site = yield* GCP.Website.TanStackStart("Web", {
rootDir: "./app",
});

Warm Instance with More Memory

const site = yield* GCP.Website.TanStackStart("Web", {
rootDir: "./app",
scaling: { minInstanceCount: 1 },
resources: { limits: { cpu: "1", memory: "1Gi" } },
});

Process Environment

const site = yield* GCP.Website.TanStackStart("Web", {
rootDir: "./app",
env: {
GREETING: "Hello from TanStack Start on Cloud Run!",
},
});

Read An Environment Variable From A Server Function

src/routes/index.tsx
const getGreeting = createServerFn({ method: "GET" }).handler(
() => process.env.GREETING ?? "Hello!",
);

Source: src/GCP/Website/Vinext.ts

Deploy a vinext application to Cloud Run as a long-running Node process: vinext’s Vite build, then vinext’s production server (startProdServer). The dist/ output is baked into the image; vinext, react, react-dom, and react-server-dom-webpack are installed with npm install rather than bundled.

Do not use the Cloudflare Worker entry (vinext/server/fetch-handler) — that is workerd.

During alchemy dev the site is vinext dev and no cloud resources are declared; Alchemy.remote() opts back into the live Cloud Run service.

Basic vinext App

const site = yield* GCP.Website.Vinext("Web", {
rootDir: "./app",
});

Warm Instance with More Memory

const site = yield* GCP.Website.Vinext("Web", {
rootDir: "./app",
scaling: { minInstanceCount: 1 },
resources: { limits: { cpu: "1", memory: "1Gi" } },
});

ISR / "use cache" default to in-process memory, which Cloud Run instances do not share. Set env.REDIS_URL for a durable Redis store; the adapter is injected automatically.

const site = yield* GCP.Website.Vinext("Web", {
env: {
REDIS_URL: "redis://10.0.0.3:6379",
},
});

Source: src/GCP/Website/Vite.ts

Deploy a plain Vite application to Cloud Run: a service serving the vite build output from a tiny static-file server. For client-only projects — React/Vue/Solid SPAs, index.html multi-page apps — whose entire deployable output is static assets.

The build runs through @alchemy.run/frontend-frameworks/vite with the @alchemy.run/frontend-frameworks/vite/node deploy target — the package must be installed in your project. Your project’s own vite.config.* (plugins included) drives the build.

During alchemy dev the site is Vite’s own dev server (native HMR) and no cloud resources are created — the site’s url is the dev server’s local address. Alchemy.remote() opts back into the full deployment.

Basic Vite SPA

const site = yield* GCP.Website.Vite("Web");

Project in a Subdirectory

const site = yield* GCP.Website.Vite("Web", {
rootDir: "./app",
});
const site = yield* GCP.Website.Vite("Docs", {
assets: { notFoundHandling: "404-page" },
});
const site = yield* GCP.Website.Vite("Web", {
scaling: { minInstanceCount: 1 },
resources: { limits: { cpu: "1", memory: "1Gi" } },
});
const site = yield* GCP.Website.Vite("Docs", {
vite: { outDir: "build", base: "/docs/" },
});
// `alchemy dev` starts `vite` programmatically: site.url is the local
// dev server (HMR included); no Cloud Run service is created.
const site = yield* GCP.Website.Vite("Web");

Source: src/GCP/Website/Vocs.ts

Deploy a Vocs documentation site to Cloud Run. The node target serves static assets first, then Vocs’ Waku RSC handler (/about → about/index.html, otherwise SSR).

Vocs documentation site

const docs = yield* GCP.Website.Vocs("Docs", {
rootDir: "./docs",
});

Custom output directory

const docs = yield* GCP.Website.Vocs("Docs", {
rootDir: "./docs",
outDir: "build",
});

Source: src/GCP/Website/Waku.ts

Deploy a Waku application to Cloud Run: the RSC server in a Cloud Run container, static assets (SSG pages included) baked into the image. Prerendered pages are served extensionless (/about).

Basic Waku App

const site = yield* GCP.Website.Waku("Web", {
rootDir: "./app",
});

Warm Instance with More Memory

const site = yield* GCP.Website.Waku("Web", {
rootDir: "./app",
scaling: { minInstanceCount: 1 },
resources: { limits: { cpu: "1", memory: "1Gi" } },
});