PublicRisk.ai

Deployment Guide

Complete deployment guide for PublicRisk.ai frontend and backend services

Deployment Guide

This guide covers deploying PublicRisk.ai to production, including frontend hosting, Modal backend services, and environment configuration.


Overview

PublicRisk.ai uses a hybrid architecture:

  • Frontend: React + TypeScript app hosted on Vercel
  • Backend: Python services on Modal Cloud Platform
  • Database: Supabase (PostgreSQL + Auth)
  • AI/ML: OpenRouter API for model inference

Prerequisites

Before deploying, ensure you have:

  • GitHub account with repository access
  • Vercel account (free tier works)
  • Modal account with CLI installed
  • Supabase project created
  • OpenRouter API key (for AI models)

Part 1: Frontend Deployment (Vercel)

Step 1: Import Repository to Vercel

  1. Go to vercel.com/new
  2. Click Import Git Repository
  3. Select your GitHub repository: casouth/PRAI
  4. Configure project:
    • Framework Preset: Vite
    • Root Directory: frontend
    • Build Command: npm run build
    • Output Directory: dist

Step 2: Configure Environment Variables

In Vercel dashboard → SettingsEnvironment Variables, add:

# API Configuration
VITE_API_URL=https://publicrisk--publicrisk-consolidated-backend-serve.modal.run
VITE_ENVIRONMENT=production
VITE_APP_VERSION=4.2.0

# Authentication
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-supabase-anon-key

# AI Models
VITE_OPENROUTER_API_KEY=your-openrouter-api-key
VITE_DEFAULT_AI_MODEL=moonshot/v1/moonshot-kimi-k2-thinking-general

# Features
VITE_ENABLE_HAZUS=true
VITE_ENABLE_2FA=true
VITE_ENABLE_STORM=true

# Analytics (Optional)
VITE_ANALYTICS_ID=your-analytics-id
# API Configuration
VITE_API_URL=http://localhost:8000
VITE_ENVIRONMENT=development
VITE_APP_VERSION=4.2.0-dev

# Authentication
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-supabase-anon-key

# AI Models
VITE_OPENROUTER_API_KEY=your-openrouter-api-key
VITE_DEFAULT_AI_MODEL=moonshot/v1/moonshot-kimi-k2-thinking-general

# Features
VITE_ENABLE_HAZUS=true
VITE_ENABLE_2FA=true
VITE_ENABLE_STORM=true

Step 3: Deploy

Click Deploy. Vercel will:

  1. Build your application (~2-3 minutes)
  2. Deploy to production URL
  3. Set up auto-deployment from main branch

Production URL: https://your-app.vercel.app


Auto-Deployment from GitHub

Every push to main automatically deploys:

git add .
git commit -m "feat: Add new feature"
git push origin main
# Vercel auto-deploys in ~2 minutes

Preview deployments: Pull requests get unique URLs for testing.


Rollback to Previous Version

In Vercel dashboard:

  1. Go to Deployments
  2. Find working deployment
  3. Click Promote to Production

Part 2: Backend Deployment (Modal)

Step 1: Install Modal CLI

# Install Modal
pip install modal

# Authenticate
modal token new

Follow prompts to authenticate with your Modal account.


Step 2: Deploy Core Services

Navigate to frontend/modal-services/core/ and deploy each service:

# Deploy HAZUS disaster risk service
cd modal-services/core
modal deploy modal_hazus_service.py

# Verify deployment
modal app list | grep hazus

Endpoint: https://publicrisk--publicrisk-hazard-service-*.modal.run

Key endpoints: /health, /assess-property, /realtime-all

# Deploy DSPy optimized query service
modal deploy modal_dspy_optimized_service.py

# Verify
modal app list | grep dspy

Endpoint: https://publicrisk--dspy-optimized-service-*.modal.run

Key endpoints: /api/dspy/query, /api/dspy/storm/generate

# Deploy SIPMath probabilistic risk service
modal deploy modal_sipmath_service.py

# Verify
modal app list | grep sipmath

Endpoint: https://publicrisk--publicrisk-sipmath-*.modal.run

Key endpoints: /api/sipmath/create-slurp, /api/sipmath/hazus-to-sip

# Deploy PEFT domain adapters service
modal deploy modal_peft_service.py

# Verify
modal app list | grep peft

Endpoint: https://publicrisk--publicrisk-peft-adapters-*.modal.run

Key endpoints: /api/peft/adapters, /api/peft/generate

# Deploy cybersecurity KEV service
modal deploy modal_cyber_service.py

# Verify
modal app list | grep cyber

Endpoint: https://publicrisk--publicrisk-cyber-*.modal.run

Key endpoints: /api/cyber/kev, /api/cyber/infrastructure-threats


Step 3: Deploy Consolidated Backend

The consolidated backend unifies all services:

cd frontend
modal deploy modal_consolidated_backend.py

Endpoint: https://publicrisk--publicrisk-consolidated-backend-serve.modal.run

This is the main API endpoint used by the frontend (VITE_API_URL).


Step 4: Configure Modal Secrets

Store sensitive credentials in Modal secrets:

# OpenRouter API key
modal secret create openrouter-api-key OPENROUTER_API_KEY=sk-or-v1-...

# Supabase credentials
modal secret create supabase-credentials \
  SUPABASE_URL=https://your-project.supabase.co \
  SUPABASE_KEY=your-service-role-key

# Redis connection (if using)
modal secret create redis-credentials \
  REDIS_URL=redis://default:password@host:port

Secrets are automatically available to deployed services.


Part 3: Database Setup (Supabase)

Step 1: Create Supabase Project

  1. Go to supabase.com
  2. Create new project
  3. Note your Project URL and anon key

Step 2: Run Database Migrations

Execute SQL in Supabase SQL Editor:

-- Users table
CREATE TABLE users (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  email TEXT UNIQUE NOT NULL,
  name TEXT,
  role TEXT DEFAULT 'User',
  client_id UUID REFERENCES client_organizations(id),
  two_factor_enabled BOOLEAN DEFAULT FALSE,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

-- Client organizations table
CREATE TABLE client_organizations (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  name TEXT NOT NULL,
  contact_email TEXT,
  max_users INTEGER DEFAULT 10,
  subscription_tier TEXT DEFAULT 'basic',
  status TEXT DEFAULT 'active',
  created_at TIMESTAMP DEFAULT NOW()
);

-- Audit logs table
CREATE TABLE audit_logs (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  user_id UUID REFERENCES users(id),
  action TEXT NOT NULL,
  resource TEXT,
  status TEXT,
  ip_address TEXT,
  created_at TIMESTAMP DEFAULT NOW()
);

-- Enable Row Level Security
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE client_organizations ENABLE ROW LEVEL SECURITY;
ALTER TABLE audit_logs ENABLE ROW LEVEL SECURITY;

-- Create policies (example)
CREATE POLICY "Users can view own data"
  ON users FOR SELECT
  USING (auth.uid() = id);

Step 3: Configure Authentication

In Supabase dashboard → AuthenticationProviders:

  1. Enable Email provider
  2. Configure email templates (optional)
  3. Set up 2FA settings (optional)

Part 4: Verification & Testing

Frontend Health Check

Visit your Vercel URL and verify:

  • ✅ Landing page loads
  • ✅ Login works
  • ✅ Dashboard displays correctly
  • ✅ No console errors

Backend Health Checks

Test each Modal service:

# Consolidated backend
curl https://publicrisk--publicrisk-consolidated-backend-serve.modal.run/health

# HAZUS service
curl https://publicrisk--publicrisk-hazard-service-*.modal.run/health

# DSPy service
curl https://publicrisk--dspy-optimized-service-*.modal.run/health

All should return {"status": "healthy"}.


End-to-End Test

  1. Login: Authenticate as test user
  2. Query Explorer: Run sample query
  3. HAZUS: Assess property risk (34.0522, -118.2437)
  4. STORM: Generate test document
  5. RAG Upload: Upload sample PDF

All features should work without errors.


Part 5: Production Configuration

Performance Optimization

Vercel:

  • Enable Edge Caching for static assets
  • Use Image Optimization for images
  • Enable Analytics for monitoring

Modal:

  • Keep services warm (increase keep_warm parameter)
  • Use Redis caching for frequently accessed data
  • Enable auto-scaling for high traffic

Security Best Practices

Important: Follow these security guidelines for production deployments.

  1. API Keys: Never commit secrets to Git

    # Use .env.local for local development
    echo ".env.local" >> .gitignore
  2. CORS: Restrict origins in Modal backend

    allowed_origins = [
        "https://your-app.vercel.app",
        "https://custom-domain.com"
    ]
  3. Rate Limiting: Enable in Modal services

    @app.function(
        concurrency_limit=100,  # Max concurrent requests
        timeout=30  # Request timeout
    )
  4. 2FA: Require for admin users

    // Enable in Supabase dashboard
    // Enforce in frontend AuthContext

Monitoring & Logging

Vercel Analytics:

  • View deployment logs in dashboard
  • Monitor Core Web Vitals
  • Track errors with Sentry (optional)

Modal Logs:

# View service logs
modal app logs publicrisk-consolidated-backend

# Follow logs in real-time
modal app logs --follow publicrisk-hazard-service

Supabase Logs:

  • View in dashboard → Logs
  • Monitor auth events
  • Track database performance

Part 6: Custom Domain Setup

Add Custom Domain to Vercel

  1. Go to Vercel dashboard → Domains
  2. Click Add Domain
  3. Enter your domain (e.g., app.publicrisk.ai)
  4. Follow DNS configuration instructions

DNS Configuration:

Type: A
Name: app
Value: 76.76.21.21 (Vercel IP)

Type: CNAME
Name: www
Value: cname.vercel-dns.com

Changes take 24-48 hours to propagate.


Part 7: Client-Specific Deployments

For clients needing private RAG stores, deploy dedicated backends:

# Deploy client-specific backend
.\deploy-client-backend.ps1 `
  -ClientName "springfield" `
  -AllowedIPs "203.0.113.0/24,198.51.100.50"

Generates:

  • client-configs/springfield.json - Full configuration
  • client-configs/springfield.env - Environment variables

Send to client:

# client-configs/springfield.env
VITE_CLIENT_RAG_ENDPOINT=https://publicrisk--springfield-rag-backend.modal.run
VITE_CLIENT_API_KEY=aB3dE9fG2hK5mN7pQ8rS1tU4vW6xY0zA
VITE_CLIENT_NAME=springfield

Client adds these to their .env file and restarts the app.


Part 8: CI/CD Automation

GitHub Actions (Optional)

Create .github/workflows/deploy.yml:

name: Deploy to Production

on:
  push:
    branches: [main]

jobs:
  deploy-frontend:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 18
      - run: npm ci
        working-directory: frontend
      - run: npm run build
        working-directory: frontend
      # Vercel auto-deploys, no explicit step needed

  deploy-backend:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      - run: pip install modal
      - run: modal token set --token-id ${{ secrets.MODAL_TOKEN_ID }} --token-secret ${{ secrets.MODAL_TOKEN_SECRET }}
      - run: modal deploy modal_consolidated_backend.py
        working-directory: frontend

Required secrets (in GitHub repo settings):

  • MODAL_TOKEN_ID
  • MODAL_TOKEN_SECRET

Troubleshooting

Frontend Issues

Problem: White screen after deployment

Solutions:

  1. Check Vercel build logs for errors
  2. Verify environment variables are set
  3. Test locally with production build: npm run build && npm run preview
  4. Clear browser cache

Problem: API calls failing with CORS errors

Solutions:

  1. Verify VITE_API_URL matches Modal endpoint
  2. Check Modal CORS configuration
  3. Ensure Vercel domain is whitelisted in Modal

Backend Issues

Problem: Modal service cold starts (30-60s delay)

Solutions:

  1. Increase keep_warm parameter:
    @app.function(keep_warm=2)  # Keep 2 containers warm
  2. Use Redis caching for frequent queries
  3. Implement health check endpoints to ping services

Problem: Modal deployment fails

Solutions:

  1. Verify Modal CLI is authenticated: modal token new
  2. Check file paths are correct
  3. Review Modal logs: modal app logs <app-name>
  4. Ensure all dependencies in requirements.txt

Database Issues

Problem: Supabase connection errors

Solutions:

  1. Verify credentials in environment variables
  2. Check Supabase project status
  3. Review database logs in Supabase dashboard
  4. Ensure RLS policies allow access

Deployment Checklist

Use this checklist for every production deployment.

Pre-Deployment

  • All tests passing locally
  • Environment variables configured
  • Database migrations reviewed
  • API keys secured (not in code)
  • CORS settings configured
  • Build succeeds locally

Deployment

  • Frontend deployed to Vercel
  • Backend services deployed to Modal
  • Custom domain configured (if applicable)
  • SSL certificates active
  • Health checks passing

Post-Deployment

  • Smoke tests completed
  • Login/authentication working
  • API endpoints responding
  • Database connections stable
  • Monitoring enabled
  • Documentation updated

Rollback Procedures

Frontend Rollback (Vercel)

  1. Go to Vercel dashboard → Deployments
  2. Find last working deployment
  3. Click Promote to Production

Backend Rollback (Modal)

  1. Find previous deployment:

    modal app list --all
  2. Redeploy previous version:

    git checkout <previous-commit>
    modal deploy modal_consolidated_backend.py

Database Rollback (Supabase)

  1. Run rollback SQL script (pre-prepared)
  2. Restore from backup if needed (Supabase automatic backups)

Production Monitoring

Key Metrics to Track

MetricToolTarget
Frontend Load TimeVercel Analyticsless than 2s
API Response TimeModal Logsless than 500ms
Error RateSentry/Vercelless than 0.1%
UptimeStatus Pagegreater than 99.9%
Cold Start FrequencyModal Logsless than 5%

Alerting

Set up alerts for:

  • ❌ API response time greater than 1s (5 min average)
  • ❌ Error rate greater than 1% (1 min spike)
  • ❌ Service downtime (immediate)
  • ❌ Database connection failures

Cost Optimization

Vercel

  • Free tier: 100GB bandwidth/month
  • Upgrade triggers:
    • greater than 100GB bandwidth
    • Need advanced analytics
    • Need team collaboration
  • Pricing: Pay-per-use (CPU/GPU seconds)
  • Optimization:
    • Use keep_warm=0 for low-traffic services
    • Cache responses with Redis
    • Batch requests when possible

Supabase

  • Free tier: 500MB database, 2GB bandwidth
  • Upgrade triggers:
    • greater than 500MB data
    • Need point-in-time recovery
    • Need custom domains


Support

For deployment assistance:


Changelog

DateVersionChanges
2025-12-044.2.0Initial comprehensive deployment guide
2025-11-154.1.0HAZUS production deployment
2025-10-304.0.0Modal backend consolidation

On this page