SourcAI — Deployment Guide
SourcAI — Deployment Guide
Architecture
[Browser] → [Railway: sourcai-frontend] → [Railway: sourcai-backend] → [Claude API]
↓
[Persistent Volume: /app/workspace-volume]
- Frontend: Next.js 14 on Railway (auto-deploy from
main, root:frontend/) - Backend: FastAPI on Railway (auto-deploy from
main, root:backend/) - Storage: Railway persistent volume at
/app/workspace-volume— survives redeploys - No tunnel needed. Both services on Railway with fixed URLs.
URLs
| Service | URL |
|---|---|
| Frontend | https://sourcai-frontend-production.up.railway.app |
| Backend | https://sourcai-backend-production.up.railway.app |
| Backend local | http://localhost:8000 |
Railway IDs
| Resource | ID |
|---|---|
| Project | 1bb90be6-d0ec-45aa-b6a1-5fba984ed1aa |
| Frontend service | 4680a1ed-0fb2-476d-86b9-61e39bda57f1 |
| Backend service | 24c5efb9-fce3-43c2-a0bd-59a8c67a3149 |
| Backend volume | 4942b3a0-756e-45ec-9196-3f06a1e1e5c7 |
| Environment | 0d324797-f561-425a-a08c-31555757ff7f |
How it works
- Push to
main→ Railway auto-deploys both services - Backend Dockerfile strips
claude-agent-sdk(macOS-only wheel) and re-locks deps for Linux entrypoint.shseeds the persistent volume with git-baked request data (datasets, templates, CLAUDE.md, existing requests) — only copies what doesn’t already exist in the volume- New requests created at runtime persist in the volume between deploys
- Frontend reads
NEXT_PUBLIC_API_URLenv var → points to Railway backend (fixed URL)
Local development
cd /Users/styreep/cofoundy/projects/starthack-2026/backend
uv run uvicorn app.main:app --port 8000
To point the live frontend at your local backend for testing:
https://sourcai-frontend-production.up.railway.app/?api=http://localhost:8000
Verify
# 1. Backend health
curl https://sourcai-backend-production.up.railway.app/health
# 2. Processed requests
curl https://sourcai-backend-production.up.railway.app/api/requests | python3 -c "import json,sys; print(f'{len(json.load(sys.stdin))} requests')"
# 3. Frontend loads
curl -s -o /dev/null -w "HTTP %{http_code}" https://sourcai-frontend-production.up.railway.app/
Demo mode fallback
When the backend is unreachable, the frontend automatically enters demo mode:
- Shows 5 mock processed requests
- Shows 8 mock dataset requests with working filters
- Agent run uses animated mock data
- All tabs (New Request, Dataset, Processed) are functional
WARNING: Demo mode is silent — no banner or indicator. If you see generic data (Dell Precision 5690, always the same 3 suppliers), you’re in demo mode. Always verify with the health check.
localStorage gotcha
The frontend stores the API URL in localStorage['sift_api_url']. This takes priority over the env var. If anyone previously visited with ?api=SOME_OLD_TUNNEL_URL, their browser will keep hitting that dead URL.
Fix: Visit once with the correct URL to update localStorage:
https://sourcai-frontend-production.up.railway.app/?api=https://sourcai-backend-production.up.railway.app
CI/CD
- Every push to
maintriggers Railway auto-deploy for both services - Frontend root:
frontend/—npm install && npx next build - Backend root:
backend/— Dockerfile with uv - Next.js 14.2.35 (upgraded from 14.2.21 to fix CVE-2025-55184 and CVE-2025-67779)
Backend env vars (Railway)
| Var | Value |
|---|---|
ANTHROPIC_API_KEY | sk-ant-... (set via Railway) |
PORT | Auto-injected by Railway |
Persistent volume details
- Mount path:
/app/workspace-volume - Symlinked to:
/app/workspace(viaentrypoint.sh) - Contains:
data/(datasets),requests/REQ-*/(processed requests),CLAUDE.md(agent prompt),templates/ - Seed logic: On each deploy,
entrypoint.shcopies new data from git into the volume without overwriting existing requests