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.
Install
Section titled “Install”pnpm add -D https://pkg.alchemy.run/@alchemy.run/frontend-frameworks/a870ed4bun add -d https://pkg.alchemy.run/@alchemy.run/frontend-frameworks/a870ed4npm install -D https://pkg.alchemy.run/@alchemy.run/frontend-frameworks/a870ed4yarn add -D https://pkg.alchemy.run/@alchemy.run/frontend-frameworks/a870ed4Docker has to be running when you deploy.
Scaffold the app
Section titled “Scaffold the app”Start from Vite’s React + TypeScript template:
pnpm create vite web --template react-tscd web && pnpm install && cd ..bun create vite@latest web -- --template react-tscd web && bun install && cd ..npm create vite@latest web -- --template react-tscd web && npm install && cd ..yarn create vite web --template react-tscd web && yarn install && cd ..The app lands in ./web/ with its own vite.config.ts. Keep it as it
is. You don’t need an adapter.
Deploy the site
Section titled “Deploy the site”Point rootDir at the app:
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 }; }),);bun alchemy deployAdd client-side routes
Section titled “Add client-side routes”Install React Router in the app:
pnpm add react-router-dombun add react-router-domnpm install react-router-domyarn add react-router-domimport { 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.
Call an API
Section titled “Call an API”Pass a Cloud Run service’s URL to the build:
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.
Local development
Section titled “Local development”alchemy dev runs Vite’s dev server with hot reload.