Platform & deployment
Deployment
Halo is live, not a localhost demo: the FastAPI backend runs on Railway and the Next.js web app runs on Vercel.
Where it runs
The monorepo splits cleanly into two independently deployed services:
| Service | Path | Host |
|---|---|---|
| Web app (landing, dashboard, war room, these docs) | apps/web | Vercel |
| Workflow API (state machine, mode logic, gateway calls) | apps/api | Railway |
The live app is at haloagent.xyz, and this documentation is served from the same deployment at /docs.
Backend on Railway
The API deploys from apps/api (Railway Root Directory = apps/api) using the in-repo Dockerfile. On every boot the container creates its tables, seeds the demo incidents, and then starts Uvicorn bound to Railway's injected $PORT:
python -c "import app.db.models; from app.db.session import create_db_and_tables; create_db_and_tables()" \
&& python scripts/seed_resilience_demo.py \
&& python scripts/seed_live_approval_demo.py \
&& uvicorn app.main:app --host 0.0.0.0 --port ${PORT:-8000}Railway exposes it on a public HTTPS URL (for example https://halo-api-production.up.railway.app). Configuration — the TrueFoundry gateway URL, saved-agent IDs, and the Jaguar action bridge — comes from environment variables; see Run it locally for the full list.
Frontend on Vercel
The web app deploys from apps/web (Vercel Root Directory = apps/web) as a standard Next.js 15 project. It needs exactly one environment variable to find the backend:
NEXT_PUBLIC_API_BASE_URL=https://<your-railway-url>Because it is a NEXT_PUBLIC_ variable it is baked in at build time, so it has to be set before the build. If it is unset, the app falls back to http://127.0.0.1:8000 for local development.
How they connect
All of the frontend's API calls run server-side — from server components and server actions — so the browser never talks to the backend directly. That means the two services only need the Railway URL wired into Vercel; no CORS setup is requiredfor the app to work. The backend just has to be reachable from Vercel over HTTPS.
State & demo data
The API uses SQLite, which is ephemeral on Railway — the file is wiped on every redeploy or restart. That is intentional: the boot command reseeds the demo incidents each time, so the deployment always comes up in a clean, known state. Don't attach a volume expecting persistence.
NEXT_PUBLIC_API_BASE_URL — open haloagent.xyz and the dashboard lists live incidents straight from the Railway API.