Overview

The RippleCore Consultant App is a specialized portal for sustainability consultants managing multiple client organizations. This guide covers deployment configuration specific to the consultant app.
App Type: Next.js 16 with React 19Port: 3008 (development), 3000 (production)Dependencies: PostgreSQL 18, Redis 7, better-authFeatures: Portfolio analytics, white-label theming, client management

Prerequisites

Before deploying the consultant app, ensure you have:
1

Infrastructure Running

  • PostgreSQL 18 database (shared with main app)
  • Redis 7 cache (shared with main app)
  • Domain name configured (e.g., consultant.yourdomain.com)
2

Main App Deployed

The consultant app shares infrastructure with the main RippleCore app:
  • Deploy main app first (see Deployment Overview)
  • Ensure database schema is up to date
  • Verify Redis is accessible from consultant app
3

Environment Configured

  • All required environment variables ready
  • OpenAI API key for AI theme generation (optional)
  • Email service configured (Resend recommended)
Important: The consultant app must share the same database and Redis instance as the main RippleCore app for multi-tenant functionality to work correctly.

Environment Variables

Required Variables

Create apps/consultant/.env.production with these variables:
# Required - Core Configuration
NODE_ENV=production
PORT=3008

# Required - Database & Cache
DATABASE_URL="postgresql://user:password@host:5432/ripplecore"
REDIS_URL="redis://:password@host:6379"

# Required - Authentication (use same secret as main app)
BETTER_AUTH_SECRET="your-secret-min-32-chars"
BETTER_AUTH_URL="https://consultant.yourdomain.com"
BETTER_AUTH_TRUST_HOST=true

# Required - Public URLs
NEXT_PUBLIC_CONSULTANT_URL="https://consultant.yourdomain.com"
NEXT_PUBLIC_APP_URL="https://app.yourdomain.com"

# App Identification
NEXT_PUBLIC_APP_NAME="RippleCore Consultant"
NEXT_PUBLIC_APP_TYPE=consultant

Optional Variables

# AI Theme Generation (recommended for consultants)
OPENAI_API_KEY="sk-..."

# Email Service (for client invitations)
RESEND_TOKEN="re_..."
RESEND_FROM="consultant@yourdomain.com"

# Rate Limiting (recommended)
ARCJET_KEY="aj_..."

# Analytics (optional)
NEXT_PUBLIC_GA_MEASUREMENT_ID="G-..."
Security Best Practice: Use the same BETTER_AUTH_SECRET across all RippleCore apps (main, consultant, charity, council) for session sharing to work correctly.

Deployment Methods


Port Configuration

Development

Port 3008 is used for local development:
# Start consultant app in dev mode
pnpm --filter consultant dev

# Access at http://localhost:3008

Production

Port 3008 (internal) with reverse proxy for external access:

Internal Port

3008 - Container/app listens hereDocker, PM2, or systemd expose this port internally

External Port

80/443 - Public HTTPS via reverse proxyTraefik, Nginx, or Caddy routes traffic from 443 → 3008

Multi-App Deployment

Deploying Multiple RippleCore Apps

The consultant app is typically deployed alongside the main RippleCore app:
1

Deploy Infrastructure

  • PostgreSQL 18 (shared database)
  • Redis 7 (shared cache)
  • Traefik or Nginx (reverse proxy)
2

Deploy Main App

3

Deploy Consultant App

  • Domain: consultant.yourdomain.com
  • Port: 3008
  • Use same DATABASE_URL and REDIS_URL
4

Optional: Deploy Other Apps

  • Marketing: www.yourdomain.com (port 3001)
  • API: api.yourdomain.com (port 3002)
  • Council: council.yourdomain.com (port 3010)
  • Charity: charity.yourdomain.com (port 3009)
Shared Infrastructure: All RippleCore apps share the same PostgreSQL database and Redis cache for multi-tenant data isolation and session management.

Resource Requirements

Minimum Specifications

For the consultant app alone (not including infrastructure):

CPU

0.5 vCPU minimum1.0 vCPU recommended for 20+ clients

Memory

512 MB minimum1 GB recommended for theme generation

Storage

500 MB for applicationApplication size (no data)

Network

1 GB/month typicalDepends on consultant activity
For all RippleCore apps + infrastructure:
  • Hetzner CPX32: 4 vCPU, 8 GB RAM, €11.99/month
  • Digital Ocean: $24/month droplet (4GB RAM)
  • Linode: $12/month Dedicated 4GB

Health Checks & Monitoring

Health Endpoint

The consultant app exposes a health check endpoint: URL: https://consultant.yourdomain.com/api/health Response (healthy):
{
  "status": "ok",
  "timestamp": "2025-01-18T12:00:00Z",
  "service": "consultant-api",
  "version": "1.0.0",
  "environment": "production",
  "checks": {
    "database": { "status": "ok" },
    "redis": { "status": "ok" }
  }
}
Response (unhealthy - 503):
{
  "status": "unhealthy",
  "timestamp": "2025-01-18T12:00:00Z",
  "service": "consultant-api",
  "checks": {
    "database": {
      "status": "error",
      "message": "Connection refused"
    },
    "redis": { "status": "ok" }
  }
}

Monitoring Setup

  • Uptime Monitoring
  • Application Logs
  • Performance Metrics
Use an external service to monitor availability:Monitor this URL:
https://consultant.yourdomain.com/api/health
Alert on:
  • HTTP status != 200
  • Response time > 2 seconds
  • status field != “ok”

Deployment Checklist

Pre-Deployment

1

Verify Infrastructure

# Test database connection
psql $DATABASE_URL -c "SELECT 1"

# Test Redis connection
redis-cli -u $REDIS_URL ping
2

Run Database Migrations

# From repository root
pnpm db:generate
pnpm db:push
3

Test Build Locally

# Build consultant app
pnpm --filter consultant build

# Check for errors
pnpm --filter consultant check
4

Configure Environment

  • Copy all required environment variables
  • Generate new BETTER_AUTH_SECRET if needed:
    npx @better-auth/cli secret
    
  • Verify BETTER_AUTH_URL matches your domain

Deployment

1

Deploy to Platform

Follow platform-specific instructions:
2

Verify Health

curl https://consultant.yourdomain.com/api/health
Should return 200 OK with "status": "ok"
3

Test Authentication

  1. Navigate to https://consultant.yourdomain.com
  2. Sign in with a consultant account
  3. Verify dashboard loads correctly
  4. Test organization switcher
4

Test Core Features

  • Create a client invitation
  • Access theme editor
  • View portfolio analytics
  • Test white-label preview

Post-Deployment

1

Configure Monitoring

  • Add health check to uptime monitor
  • Set up error tracking (Sentry recommended)
  • Configure log aggregation
2

Performance Tuning

  • Review response times in production
  • Adjust container resource limits if needed
  • Enable Redis caching verification
3

Security Hardening

  • Verify SSL certificate is valid
  • Test rate limiting (Arcjet)
  • Review security headers
  • Enable CORS if needed for API access

Common Deployment Issues

Database Connection Errors

Error: ECONNREFUSED when connecting to PostgreSQLCauses:
  • Database not running
  • Incorrect DATABASE_URL
  • Network/firewall blocking connection
Solutions:
# Verify database is running
docker ps | grep postgres

# Test connection from consultant container
docker exec ripplecore-consultant psql $DATABASE_URL -c "SELECT 1"

# Check network connectivity
docker network ls
docker network inspect dokploy-network
Error: password authentication failedCauses:
  • Wrong database password in DATABASE_URL
  • User doesn’t exist
Solutions:
  • Verify DATABASE_URL format: postgresql://user:password@host:5432/database
  • Check database user exists and has correct password
  • Verify user has permissions on ripplecore database

Redis Connection Errors

Error: Error connecting to RedisSolutions:
# Verify Redis is running
docker ps | grep redis

# Test connection
redis-cli -u $REDIS_URL ping

# Check Redis URL format
# Correct: redis://:password@host:6379
# Incorrect: redis://host:6379 (missing password)

Build Failures

Error: Build fails with TypeScript errorsSolutions:
# Check for type errors
pnpm --filter consultant check

# Regenerate types from database schema
pnpm db:generate

# Clear build cache and retry
rm -rf apps/consultant/.next
pnpm --filter consultant build
Error: Module not found errorsSolutions:
# Reinstall dependencies
pnpm install --force

# Verify workspace dependencies resolve
pnpm why @repo/consultant
pnpm why @repo/theme-editor

Runtime Issues

Problem: Theme editor shows blank screen or errorsCauses:
  • Missing OPENAI_API_KEY for AI generation
  • Client-side hydration mismatch
  • Browser compatibility issue
Solutions:
  • Add OPENAI_API_KEY for AI features (optional but recommended)
  • Check browser console for errors
  • Test in Chrome/Firefox latest versions
  • Clear browser cache and cookies
Problem: Users logged out unexpectedlyCauses:
  • Redis not accessible
  • BETTER_AUTH_SECRET mismatch between apps
  • Secure cookie issues with HTTP (not HTTPS)
Solutions:
  • Verify Redis connection from consultant app
  • Ensure same BETTER_AUTH_SECRET across all apps
  • Use HTTPS in production (BETTER_AUTH_TRUST_HOST=true)
  • Check session cookies in browser DevTools

Scaling Considerations

Horizontal Scaling

The consultant app can be scaled horizontally with multiple instances: Requirements:
  • Load balancer (Traefik, Nginx, HAProxy)
  • Shared Redis for session storage
  • Shared PostgreSQL database
  • Sticky sessions NOT required (stateless)
Docker Swarm Example:
services:
  consultant:
    # ... existing config
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure

Vertical Scaling

Adjust resources based on consultant portfolio size:
ClientsvCPUMemoryNotes
1-100.5512 MBStarter consultants
10-301.01 GBGrowing portfolios
30-1002.02 GBEstablished firms
100+4.04 GBEnterprise consultants

Security Considerations

Consultant-Specific Security

Critical: Ensure consultants can only access their clients’ dataImplementation:
  • Row-level security (RLS) in PostgreSQL enforces isolation
  • organizationId filtering on all queries
  • Session validation on every request
  • Redis cache keys include organizationId
Verification:
# Test as consultant user
# Should only see organizations you manage
curl https://consultant.yourdomain.com/api/clients \
  -H 'Cookie: better-auth.session_token=...'
Recommended: Enable Arcjet rate limiting for consultant APIConfiguration:
ARCJET_KEY="aj_..."
Limits (from API reference):
  • Authenticated: 100 requests/minute
  • Bulk operations: 10 requests/minute
  • AI generation: 5 requests/minute
Test:
# Make 15 rapid requests to trigger limit
for i in {1..15}; do
  curl https://consultant.yourdomain.com/api/organizations/search?q=test
done
# Should receive 429 after request #10
Never commit secrets to gitBest Practices:
  • Use environment variables for all secrets
  • Rotate BETTER_AUTH_SECRET every 90 days
  • Store secrets in Dokploy/platform secret manager
  • Use different secrets for dev/staging/production
Required Secrets:
  • BETTER_AUTH_SECRET (32+ characters, shared across apps)
  • OPENAI_API_KEY (for AI theme generation)
  • RESEND_TOKEN (for client emails)
  • ARCJET_KEY (for rate limiting)

Updating the Consultant App

Zero-Downtime Updates

1

Backup Database

# Create backup before updates
pg_dump $DATABASE_URL > backup-$(date +%Y%m%d).sql
2

Deploy New Version

Dokploy:
  • Push to git: git push origin main
  • Dokploy auto-deploys from webhook
  • Old container stops after new one is healthy
Docker Compose:
# Pull latest code
git pull origin main

# Rebuild and restart
docker-compose up -d --build consultant
3

Run Migrations

# If database schema changed
pnpm db:generate
pnpm db:push
4

Verify Health

# Check health endpoint
curl https://consultant.yourdomain.com/api/health

# Monitor logs for errors
docker logs -f ripplecore-consultant

Troubleshooting

Deployment Verification Script

Use this script to verify your deployment:
#!/bin/bash
# verify-consultant-deployment.sh

DOMAIN="consultant.yourdomain.com"

echo "🔍 Verifying Consultant App Deployment..."

# 1. DNS Resolution
echo -n "DNS: "
if host $DOMAIN > /dev/null 2>&1; then
  echo "✅ Resolves"
else
  echo "❌ Failed"
  exit 1
fi

# 2. HTTPS Connection
echo -n "HTTPS: "
if curl -sf https://$DOMAIN/api/health > /dev/null; then
  echo "✅ Connected"
else
  echo "❌ Failed"
  exit 1
fi

# 3. Health Check
echo -n "Health: "
STATUS=$(curl -s https://$DOMAIN/api/health | jq -r '.status')
if [ "$STATUS" = "ok" ]; then
  echo "✅ Healthy"
else
  echo "❌ Unhealthy (status: $STATUS)"
  exit 1
fi

# 4. Database Check
echo -n "Database: "
DB_STATUS=$(curl -s https://$DOMAIN/api/health | jq -r '.checks.database.status')
if [ "$DB_STATUS" = "ok" ]; then
  echo "✅ Connected"
else
  echo "❌ Failed"
  exit 1
fi

# 5. Redis Check
echo -n "Redis: "
REDIS_STATUS=$(curl -s https://$DOMAIN/api/health | jq -r '.checks.redis.status')
if [ "$REDIS_STATUS" = "ok" ]; then
  echo "✅ Connected"
else
  echo "❌ Failed"
  exit 1
fi

echo ""
echo "🎉 Consultant App Deployment Verified!"

Additional Resources

Deployment Support: Contact devops@ripplecore.co.uk for deployment assistance or custom infrastructure requirements.

What’s Next?

1

Deploy the App

Follow the deployment method of your choice above
2

Invite Your First Client

Test the client invitation workflow
3

Customize Branding

Use the theme editor to create your white-label experience
4

Monitor Performance

Set up health checks and monitoring
5

Onboard Consultants

Share the Consultant Guide with your team