Calafai Docs

Local Development

Local Development

This guide covers setting up and running the Groundtruth Platform locally for development.

Prerequisites

  • Node.js 18+ (recommended: 20 LTS)
  • Python 3.12+
  • PostgreSQL (local instance or a Supabase project)
  • npm (included with Node.js)
  • Git

Optional:

  • Upstash Redis account (caching and rate limiting degrade gracefully without it)
  • Stripe CLI (for testing webhooks locally)

Clone and Install

1. Clone the Repository

git clone <repo-url>
cd groundtruth-platform

2. Install Web App Dependencies

cd apps/web
npm install

3. Install Python Engine Dependencies

cd packages/engine
python -m venv venv
source venv/bin/activate        # macOS/Linux
# venv\Scripts\activate         # Windows
pip install -r requirements.txt

Environment Variables

Web App (apps/web/.env.local)

Create this file with the following variables. See docs/operations/environment-variables.md for the full reference.

# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key

# Database (Supabase provides this under Settings > Database)
DATABASE_URL=postgresql://postgres:password@db.your-project.supabase.co:5432/postgres

# Stripe (test mode keys)
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...

# Railway engine URL (local development)
RAILWAY_ENGINE_URL=http://localhost:8000

# Upstash Redis (optional -- falls back to in-memory)
UPSTASH_REDIS_REST_URL=https://your-redis.upstash.io
UPSTASH_REDIS_REST_TOKEN=your-token

# Resend (optional -- emails will log to console if missing)
RESEND_API_KEY=re_...

# Sentry (optional)
NEXT_PUBLIC_SENTRY_DSN=https://...@sentry.io/...
SENTRY_AUTH_TOKEN=sntrys_...

Python Engine (packages/engine/.env)

# Database
DATABASE_URL=postgresql://postgres:password@db.your-project.supabase.co:5432/postgres

# LLM API keys
OPENAI_API_KEY=sk-...
XAI_API_KEY=xai-...
ANTHROPIC_API_KEY=sk-ant-...
GOOGLE_API_KEY=AIza...

# Sentry (optional)
SENTRY_DSN=https://...@sentry.io/...
ENVIRONMENT=development

Database Setup

From the apps/web directory:

# Apply all Prisma migrations (creates tables, indexes, RLS policies)
npx prisma migrate dev

# Seed the agent roster (20 agents across 8 departments)
npx prisma db seed

# Open visual database browser (runs at http://localhost:5555)
npx prisma studio

The seed script (prisma/seed.ts) populates the AgentConfig table with the full agent roster. A separate template seeder (prisma/seed-templates.ts) creates the five system engagement templates.

Running Locally

You need two terminals -- one for the Next.js web app and one for the Python engine.

Terminal 1: Next.js Dev Server

cd apps/web
npm run dev

The web app runs at http://localhost:3000.

Terminal 2: Python Engine

cd packages/engine
source venv/bin/activate
python api.py

The engine API runs at http://localhost:8000.

Verify Both Services

# Web app health check
curl http://localhost:3000/api/health

# Engine health check
curl http://localhost:8000/health

Both should return JSON with a status indicating the service is healthy.

Running Tests

The web app uses Vitest as its test framework. All 281 tests are in apps/web/src/__tests__/.

cd apps/web

# Watch mode (re-runs on file changes)
npm test

# Single run (CI mode)
npm test -- --run

# With coverage report
npm test -- --coverage

# Run a specific test file
npm test -- --run src/__tests__/api-keys/api-key-management.test.ts

# Run tests matching a pattern
npm test -- --run -t "should create engagement"

See testing.md for detailed information on test patterns and mocking strategies.

Common Issues

RAILWAY_ENGINE_URL Not Set

If the web app cannot reach the engine, ensure RAILWAY_ENGINE_URL=http://localhost:8000 is set in apps/web/.env.local. Without it, engine-related API calls (starting runs, fetching status) will fail.

Supabase Storage Bucket Missing

File uploads require a storage bucket named engagement-attachments in your Supabase project. Create it via the Supabase dashboard:

  1. Go to Storage in the Supabase dashboard
  2. Click New bucket
  3. Name: engagement-attachments
  4. Set to Private (not public)

Redis Not Available

Redis (Upstash) is entirely optional for local development. The platform degrades gracefully:

  • Caching: Falls back to no-cache (every request hits the database)
  • Rate limiting: Falls back to an in-memory token bucket (resets on server restart)

No mock or local Redis instance is needed.

Prisma Client Out of Date

If you see type errors after pulling new migrations, regenerate the Prisma client:

cd apps/web
npx prisma generate

Port Conflicts

  • Next.js defaults to port 3000. If occupied, it auto-selects the next available port.
  • The Python engine defaults to port 8000. If you change it, update RAILWAY_ENGINE_URL accordingly.

Stripe Webhooks in Development

To test Stripe webhooks locally, use the Stripe CLI:

stripe listen --forward-to localhost:3000/api/billing/webhook

This provides a temporary whsec_... secret to set as STRIPE_WEBHOOK_SECRET.

On this page