Deploying Alfonso’s Fine Flooring to edmhs.us

Two pieces: the static site (Firebase Hosting) and the advisor API (Cloud Run). Firebase rewrites /api/** to the Cloud Run service, so the browser only ever talks to one origin.

1. Deploy the advisor API to Cloud Run

From server/:

# One-time: enable APIs and set project
gcloud config set project YOUR_GCP_PROJECT
gcloud services enable run.googleapis.com artifactregistry.googleapis.com

# Build & deploy the container (name must match firebase.json serviceId)
gcloud run deploy alfonso-advisor \
  --source . \
  --region us-central1 \
  --allow-unauthenticated \
  --set-env-vars ADVISOR_MODEL=claude-haiku-4-5,ALLOWED_ORIGINS=https://edmhs.us

# Store the API key as a secret (recommended over --set-env-vars for keys)
echo -n "sk-ant-..." | gcloud secrets create anthropic-api-key --data-file=-
gcloud run services update alfonso-advisor --region us-central1 \
  --set-secrets ANTHROPIC_API_KEY=anthropic-api-key:latest

Verify: curl https://<cloud-run-url>/healthz{"ok":true,...,"configured":true}.

2. Deploy the site to Firebase Hosting

From the project root (where firebase.json lives):

firebase use YOUR_FIREBASE_PROJECT   # the "edm-web" project
firebase deploy --only hosting

firebase.json already: - serves ui_kits/website/ as the site root (index.html, the .jsx sections, measure.html), - rewrites /api/** → the alfonso-advisor Cloud Run service in us-central1.

If your Cloud Run service name or region differ, update firebase.jsonhosting.rewrites[0].run to match.

3. How the advisor call flows

ui_kits/website/FloorAdvisor.jsxask(): 1. POST /api/advisor with { message } (same-origin; Firebase forwards to Cloud Run). 2. If that fails and the in-Claude preview helper window.claude.complete exists, it falls back to that (so the design preview keeps working). 3. Otherwise it shows the friendly “advisor is offline, use the estimate form” message.

Notes

  • The API key never reaches the browser — it lives only on Cloud Run.
  • The endpoint has a simple per-IP rate limit (ADVISOR_RATE_PER_MIN, default 10/min) to cap API spend.
  • Model is swappable via the ADVISOR_MODEL env var (haiku/sonnet families).
  • The system prompt + price list in server/main.py mirror the ones in FloorAdvisor.jsx — if you change pricing, update both.