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:
Infrastructure Running
PostgreSQL 18 database (shared with main app)
Redis 7 cache (shared with main app)
Domain name configured (e.g., consultant.yourdomain.com)
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
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
Dokploy (Recommended)
Docker Compose
Standalone Server
Deploy with Dokploy The consultant app includes a dokploy.yaml configuration file for easy deployment.
Create Service in Dokploy
Open Dokploy dashboard
Navigate to your RippleCore project
Click New Service → Application
Select Git Source → Choose repository
Branch: main
Configure Build
Build Settings :
Build context: . (monorepo root)
Dockerfile path: apps/consultant/Dockerfile
Build command: Auto-detected from Dockerfile
Add Environment Variables
In Dokploy dashboard, add all required environment variables:
Copy from your .env.production file
Or use Dokploy’s .env file upload feature
Verify DATABASE_URL and REDIS_URL point to shared infrastructure
Configure Domain
Domain Settings :
Domain: consultant.yourdomain.com
SSL: Auto (Let’s Encrypt)
HTTP → HTTPS redirect: Enabled
Port: 3008 (internal), 80/443 (external via Traefik)
Deploy
Click Deploy and monitor logs for:
✅ Dependencies installed
✅ Next.js build successful
✅ Container started
✅ Health check passing
✅ SSL certificate issued
Verify Deployment :# Check health endpoint
curl https://consultant.yourdomain.com/api/health
# Expected response
{
"status" : "ok",
"timestamp" : "2025-01-18T...",
"service" : "consultant-api",
"version" : "1.0.0"
}
Deploy with Docker Compose For self-managed deployments, use Docker Compose directly.
Create docker-compose.yml
Add consultant service to your compose file: services :
consultant :
build :
context : .
dockerfile : apps/consultant/Dockerfile
container_name : ripplecore-consultant
ports :
- "3008:3008"
env_file :
- apps/consultant/.env.production
restart : unless-stopped
depends_on :
- postgres
- redis
healthcheck :
test : [ "CMD" , "curl" , "-f" , "http://localhost:3008/api/health" ]
interval : 30s
timeout : 10s
retries : 3
Build and Start
# Build the image
docker-compose build consultant
# Start the service
docker-compose up -d consultant
# View logs
docker-compose logs -f consultant
Configure Reverse Proxy
Add Nginx or Traefik configuration for SSL and domain routing: Nginx example :server {
listen 443 ssl http2;
server_name consultant.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/consultant.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/consultant.yourdomain.com/privkey.pem;
location / {
proxy_pass http://localhost:3008;
proxy_set_header Host $ host ;
proxy_set_header X-Real-IP $ remote_addr ;
proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for ;
proxy_set_header X-Forwarded-Proto $ scheme ;
}
}
Run the consultant app directly on a server without Docker.
Install Dependencies
# Install Node.js 20 LTS
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
# Install pnpm
npm install -g pnpm@10.22.0
# Clone repository
git clone https://github.com/your-org/ripplecore.git
cd ripplecore
# Install workspace dependencies
pnpm install
Build Consultant App
# Set environment variables
export DATABASE_URL = "postgresql://..."
export REDIS_URL = "redis://..."
export BETTER_AUTH_SECRET = "..."
export BETTER_AUTH_URL = "https://consultant.yourdomain.com"
export NEXT_PUBLIC_CONSULTANT_URL = "https://consultant.yourdomain.com"
# Build consultant app
pnpm --filter consultant build
Start with PM2
# Install PM2
npm install -g pm2
# Start consultant app
cd apps/consultant
pm2 start npm --name "consultant" -- start
# Save PM2 config
pm2 save
# Setup auto-restart on server reboot
pm2 startup
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:
Deploy Infrastructure
PostgreSQL 18 (shared database)
Redis 7 (shared cache)
Traefik or Nginx (reverse proxy)
Deploy Consultant App
Domain: consultant.yourdomain.com
Port: 3008
Use same DATABASE_URL and REDIS_URL
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
Recommended VPS for Full Stack
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”
View logs based on deployment method:Dokploy :# In Dokploy dashboard: Logs tab
# Or via CLI:
docker logs -f ripplecore-consultant
Docker Compose :docker-compose logs -f consultant
PM2 :pm2 logs consultant
pm2 monit # Real-time monitoring
Key metrics to monitor :
Response Time : API calls < 200ms
Memory Usage : < 1GB under normal load
CPU Usage : < 50% average
Error Rate : < 0.1%
Dashboard views : Dokploy includes basic metrics, or use:
Prometheus + Grafana for detailed metrics
Sentry for error tracking
LogDNA/Datadog for log aggregation
Deployment Checklist
Pre-Deployment
Verify Infrastructure
# Test database connection
psql $DATABASE_URL -c "SELECT 1"
# Test Redis connection
redis-cli -u $REDIS_URL ping
Run Database Migrations
# From repository root
pnpm db:generate
pnpm db:push
Test Build Locally
# Build consultant app
pnpm --filter consultant build
# Check for errors
pnpm --filter consultant check
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
Deploy to Platform
Follow platform-specific instructions:
Verify Health
curl https://consultant.yourdomain.com/api/health
Should return 200 OK with "status": "ok"
Test Authentication
Navigate to https://consultant.yourdomain.com
Sign in with a consultant account
Verify dashboard loads correctly
Test organization switcher
Test Core Features
Create a client invitation
Access theme editor
View portfolio analytics
Test white-label preview
Post-Deployment
Configure Monitoring
Add health check to uptime monitor
Set up error tracking (Sentry recommended)
Configure log aggregation
Performance Tuning
Review response times in production
Adjust container resource limits if needed
Enable Redis caching verification
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:
Clients vCPU Memory Notes 1-10 0.5 512 MB Starter consultants 10-30 1.0 1 GB Growing portfolios 30-100 2.0 2 GB Established firms 100+ 4.0 4 GB Enterprise consultants
Security Considerations
Consultant-Specific Security
Multi-Client Data Isolation
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 :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
Backup Database
# Create backup before updates
pg_dump $DATABASE_URL > backup- $( date +%Y%m%d ) .sql
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
Run Migrations
# If database schema changed
pnpm db:generate
pnpm db:push
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?
Deploy the App
Follow the deployment method of your choice above
Invite Your First Client
Test the client invitation workflow
Customize Branding
Use the theme editor to create your white-label experience
Monitor Performance
Set up health checks and monitoring