Skip to content

React SPA

This walks a plain React single-page app onto Cloud Run with GCP.Website.Vite. Client-side routes work out of the box: unknown paths answer with index.html.

Terminal window
pnpm add -D https://pkg.alchemy.run/@alchemy.run/frontend-frameworks/a870ed4

Docker has to be running when you deploy.

Start from Vite’s React + TypeScript template:

Terminal window
pnpm create vite web --template react-ts
cd web && pnpm install && cd ..

The app lands in ./web/ with its own vite.config.ts. Keep it as it is. You don’t need an adapter.

Point rootDir at the app:

alchemy.run.ts
import * as Alchemy from "alchemy";
import * as GCP from "@alchemy.run/gcp";
import * as Effect from "effect/Effect";
export const Website = GCP.Website.Vite("Website", { rootDir: "./web" });
export default Alchemy.Stack(
"MyReactApp",
{ providers: GCP.providers(), state: GCP.state() },
Effect.gen(function* () {
const site = yield* Website;
return { url: site.url };
}),
);
Terminal window
bun alchemy deploy

Install React Router in the app:

Terminal window
pnpm add react-router-dom
web/src/main.tsx
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import App from "./App.tsx";
createRoot(document.getElementById("root")!).render(
<StrictMode>
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
<Route path="/about" element={<h1>About</h1>} />
</Routes>
</BrowserRouter>
</StrictMode>,
);

Deploy again and open /about directly. The server answers with index.html and the router renders the page.

Pass a Cloud Run service’s URL to the build:

alchemy.run.ts
Effect.gen(function* () {
const api = yield* Api;
const site = yield* Website;
const site = yield* GCP.Website.Vite("Website", {
rootDir: "./web",
env: { VITE_API_URL: api.uri },
});
return { url: site.url };
}),

Read it in the app with import.meta.env.VITE_API_URL. The API needs CORS headers for the site’s origin.

alchemy dev runs Vite’s dev server with hot reload.

  • Vite — every option the resource takes.
  • Cloud Run — build the API the app calls.