Calafai Docs

Environments & Dev Setup

Environments & Dev Setup

How the Groundtruth Platform runs across local, development, and production environments. Start here if you're joining the team.

Quick Start by Role

Not everyone needs the full stack running. Pick your path:

You are...What you needSetup time
Designer / FrontendNode.js + Next.js dev server + Supabase (shared dev DB)~15 min
Full-stack devAbove + Python 3.12 + engine running locally~30 min
Infra / DevOpsAbove + Supabase branching + Railway environments~45 min

All roles: follow the Local Development guide first, then return here for environment-specific setup.


How Production Works

The platform is three services connected by environment variables:

                     Internet
                        |
              +---------+---------+
              |                   |
        +-----+------+    +------+------+
        |   Vercel   |    |   Railway   |
        |  Next.js   +--->+   Python    |
        | Web + API  |    |   Engine    |
        +-----+------+    +------+------+
              |                   |
              +---+    +----------+
                  |    |
            +-----+----+-----+
            |    Supabase     |
            |  PostgreSQL +   |
            |  Auth + Storage |
            +-----------------+
ServiceURLWhat it does
Vercel (Web App)groundtruth-platform.vercel.appNext.js frontend, API routes, Stripe webhooks, SSE proxy
Railway (Engine)groundtruth-platform-production.up.railway.appPython CrewAI engine, engagement runs (10-60 min), LLM dispatch
Supabase (Database)yyhsycogenoqrrsunkxf.supabase.coPostgreSQL (20 tables), Auth (JWT + SSO), Storage (attachments)

Supporting services: Stripe (billing), Upstash Redis (caching/rate limiting), Resend (email), Sentry (error tracking).

How a request flows

  1. Browser hits Vercel (Next.js API route)
  2. Middleware extracts tenant from JWT cookie or API key
  3. Route handler queries Supabase PostgreSQL via Prisma (RLS enforces tenant isolation)
  4. For engagement runs: Vercel calls Railway engine over HTTP, passing X-Tenant-ID header
  5. Engine uses DatabaseStorageAdapter to read/write PostgreSQL directly
  6. Real-time updates flow back via SSE: Engine -> Next.js proxy -> Browser

Why two servers?

Vercel's serverless functions have a 60-second timeout. Engagement runs take 10-60 minutes. The Python engine runs as a persistent Railway service — no timeout.


Environment Matrix

Three environments, each with its own set of service instances:

ComponentLocal DevDev BranchProduction
Web Applocalhost:3000Vercel Preview (auto)groundtruth-platform.vercel.app
Enginelocalhost:8000Shared dev Railway envgroundtruth-platform-production.up.railway.app
DatabaseSupabase branch (or shared dev)Supabase branchProduction Supabase
AuthSupabase (shared dev project)Supabase branchProduction Supabase
StorageSupabase StorageSupabase branchProduction Supabase
StripeTest mode (sk_test_)Test mode (sk_test_)Live mode (sk_live_)
RedisOptional (or Upstash dev)Upstash dev instanceUpstash production
EmailConsole loggingResend testResend production
SentryOptionalDev projectProduction project

Environment Variable Reference

Below is every env var and what value it should have per environment.

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

VariableLocal DevDev Branch (Vercel)Production (Vercel)
NEXT_PUBLIC_SUPABASE_URLBranch/dev project URLBranch project URLhttps://yyhsycogenoqrrsunkxf.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEYBranch/dev anon keyBranch anon keyProduction anon key
SUPABASE_SERVICE_ROLE_KEYBranch/dev service keyBranch service keyProduction service key
DATABASE_URLBranch/dev direct URLBranch direct URLProduction direct URL
STRIPE_SECRET_KEYsk_test_...sk_test_...sk_live_...
STRIPE_WEBHOOK_SECRETStripe CLI whsec_...Stripe test whsec_...Stripe live whsec_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYpk_test_...pk_test_...pk_live_...
RAILWAY_ENGINE_URLhttp://localhost:8000Shared dev Railway URLProduction Railway URL
UPSTASH_REDIS_REST_URLOptionalDev Upstash URLProduction Upstash URL
UPSTASH_REDIS_REST_TOKENOptionalDev Upstash tokenProduction Upstash token
RESEND_API_KEYOptional (logs to console)re_... (test)re_... (production)
NEXT_PUBLIC_SENTRY_DSNOptionalDev DSNProduction DSN
SENTRY_AUTH_TOKENOptionalDev tokenProduction token

Engine (packages/engine/.env)

VariableLocal DevDev RailwayProduction Railway
DATABASE_URLBranch/dev direct URLBranch pooler URL (port 6543)Production pooler URL (port 6543)
OPENAI_API_KEYYour keyShared dev keyProduction key
XAI_API_KEYYour keyShared dev keyProduction key
ANTHROPIC_API_KEYYour keyShared dev keyProduction key
GOOGLE_API_KEYYour keyShared dev keyProduction key
ALLOWED_ORIGINShttp://localhost:3000Vercel preview URLhttps://groundtruth-platform.vercel.app
SENTRY_DSNOptionalDev DSNProduction DSN
ENVIRONMENTdevelopmentdevelopmentproduction

Important: Railway engine on dev uses the Supabase connection pooler URL (port 6543), not the direct connection. This prevents connection exhaustion.


Setting Up a Dev Branch

A "dev branch" means three things happening together:

  1. Git branch — your feature/bugfix branch
  2. Vercel Preview — automatic, deployed on every push (no setup needed)
  3. Supabase Branch — isolated database with its own schema, auth, and storage

Step 1: Create a Git Branch

git checkout -b feature/my-feature

Step 2: Supabase Branching (Requires Pro Plan)

Supabase branching gives you an isolated database instance that starts with your production schema (all migrations applied) but no production data. This is ideal for testing migrations and schema changes safely.

Via Supabase Dashboard

  1. Go to your project at supabase.com
  2. Click the branch selector (top-left, next to project name)
  3. Click Create branch
  4. Name it to match your git branch (e.g., feature/my-feature)
  5. Wait for provisioning (~1-2 minutes)
  6. The dashboard shows the branch's unique credentials:
    • Project URL (different from production)
    • Anon key (different from production)
    • Service role key (different from production)
    • Database URL (different from production)

Via Supabase CLI

# Install Supabase CLI if you haven't
brew install supabase/tap/supabase

# Link to your project (one-time)
supabase link --project-ref yyhsycogenoqrrsunkxf

# Create a branch
supabase branches create feature/my-feature

# List branches
supabase branches list

# Get branch credentials
supabase branches get feature/my-feature

What branches include

  • Fresh PostgreSQL instance with all migrations applied
  • Separate Auth instance (its own JWT keys)
  • Separate Storage instance (empty — no production files)
  • No production data — you must seed: npx prisma db seed

What branches do NOT include

  • Production data (tables are empty after migrations)
  • Edge Functions (Supabase Edge Functions, not our Railway engine)
  • Custom domains

Step 3: Update Your Local .env.local

Point your local dev server at the branch database:

# apps/web/.env.local — update these four values from branch credentials
NEXT_PUBLIC_SUPABASE_URL=https://BRANCH_REF.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...branch-anon-key...
SUPABASE_SERVICE_ROLE_KEY=eyJ...branch-service-key...
DATABASE_URL=postgresql://postgres:PASSWORD@db.BRANCH_REF.supabase.co:5432/postgres

Step 4: Seed the Branch Database

The branch has the schema but no data:

cd apps/web

# Apply any new migrations not yet in the branch
npx prisma migrate deploy

# Seed agents and templates
npx prisma db seed

Step 5: Vercel Preview (Automatic)

When you push your branch, Vercel automatically creates a preview deployment. The preview URL looks like:

https://groundtruth-platform-<hash>-<team>.vercel.app

For the preview to use your Supabase branch, set branch-specific env vars in Vercel:

  1. Go to Vercel project Settings > Environment Variables
  2. For each Supabase variable (NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, etc.), add an override scoped to your Preview environment
  3. Or use Vercel's Git branch-based env var overrides

Tip: For quick local testing, just update .env.local. Vercel preview env var overrides are only needed when you want the deployed preview to also use the branch database.

Step 6: Configure Auth Redirects

Add your local and preview URLs to Supabase Auth redirect allowlist (on the branch):

  1. In the Supabase branch dashboard, go to Authentication > URL Configuration
  2. Add:
    • http://localhost:3000/auth/callback
    • https://groundtruth-platform-<hash>.vercel.app/auth/callback

Step 7: Railway Engine (Shared Dev)

For most development work, the engine isn't needed (UI, API routes, billing all run on Vercel). When you do need it:

Option A: Run locally (recommended for engine work)

cd packages/engine
source venv/bin/activate
python api.py  # Runs on localhost:8000

Set RAILWAY_ENGINE_URL=http://localhost:8000 in .env.local.

Option B: Shared dev Railway environment (for team-wide testing)

  • Create a second Railway environment named development
  • Deploy the develop branch to it
  • Set its DATABASE_URL to the Supabase branch connection pooler
  • Share the URL with the team as RAILWAY_ENGINE_URL for dev

Git Workflow

feature/xyz  ──push──>  Vercel Preview  ──>  Supabase Branch
     |                                          (isolated DB)
     |
     ├── PR review + preview testing
     |
     v
   main  ──auto-deploy──>  Vercel Production  ──>  Supabase Production
                                                    (live data)

Branch Naming

PatternPurpose
feature/short-descriptionNew features
fix/short-descriptionBug fixes
docs/short-descriptionDocumentation
refactor/short-descriptionCode restructuring

Merge Checklist

Before merging to main:

  • npm run build passes locally (no type errors)
  • Tests pass: npm test -- --run
  • If schema changed: migration file committed (npx prisma migrate dev --name descriptive_name)
  • Supabase branch tested (seed + migrate + basic smoke test)
  • Preview deployment loads and key flows work
  • PR reviewed

After Merge

  1. Vercel auto-deploys to production
  2. If there are new Prisma migrations, they apply automatically via the Vercel build command (npx prisma migrate deploy && next build — configured in vercel.json or Vercel dashboard)
  3. Delete the Supabase branch (dashboard or supabase branches delete feature/xyz)

Working Without the Engine

If you're working on frontend, API routes, billing, or settings — you likely don't need the Python engine running. The web app works independently for:

  • All dashboard pages and navigation
  • Settings (billing, team, branding, API keys, webhooks, SSO)
  • Engagement creation and editing
  • Template management
  • Client portal
  • Analytics dashboard

You only need the engine for:

  • Starting engagement runs (the "Run" button)
  • Viewing live run progress (Mission Control SSE stream)
  • Testing deliverable generation

Without the engine, the "Start Run" button will show an error, but everything else works normally.


Supabase Branch Lifecycle

Create branch  ──>  Develop + test  ──>  Merge migrations  ──>  Delete branch
                         |
                    Seed data
                    Test migrations
                    Validate schema

Handling Migration Drift

If production gets new migrations while your branch is active:

# Rebase your branch to pick up production migrations
supabase branches rebase feature/my-feature

# Or reset (destroys branch data, re-applies all migrations)
supabase branches reset feature/my-feature

Cost

Supabase branches are included in the Pro plan ($25/month). Each branch consumes compute while active. Delete branches you're not using.


Troubleshooting

"Cannot reach engine" on dev branch

Your RAILWAY_ENGINE_URL is probably still pointing at production or is unset. For local dev, set it to http://localhost:8000 and run the engine locally. If you don't need the engine, ignore this — the web app works fine without it.

Auth redirects failing on preview

The Supabase branch needs your preview URL in its redirect allowlist. Go to the branch's Authentication > URL Configuration and add the preview URL with /auth/callback.

Empty database after creating branch

Expected. Supabase branches apply migrations (schema) but don't copy production data. Run npx prisma db seed to populate agents and templates.

"Prisma Client out of date" after switching branches

Regenerate the client:

cd apps/web
npx prisma generate

Branch database won't connect

Check that you're using the branch's credentials (URL, anon key, service key), not production's. Each branch has its own unique connection string.


On this page