This comprehensive guide provides everything new developers need to set up and start contributing to the Churn Saver project. Follow these instructions to get your development environment running quickly and independently.
- Prerequisites
- Local Environment Setup
- Database Setup
- Testing Procedures
- Common Debugging Scenarios
- Development Server Startup
Before setting up the development environment, ensure you have the following installed:
| Component | Version | Installation |
|---|---|---|
| Node.js | 18.0.0+ | Download from nodejs.org |
| pnpm | 8.0.0+ | npm install -g pnpm |
| PostgreSQL | 14.0+ | Download from postgresql.org |
| Git | 2.0+ | Download from git-scm.com |
- Visit whop.com/developers
- Create a developer account
- Create a new application
- Generate API credentials:
- App ID
- API Key
- Webhook Secret
Run these commands to verify prerequisites:
# Check Node.js version
node --version # Should show v18.x.x or higher
# Check pnpm version
pnpm --version # Should show 8.x.x or higher
# Check PostgreSQL
psql --version # Should show 14.x or higher
# Check Git
git --version # Should show 2.x.x or highergit clone https://github.com/your-org/churn-saver.git
cd churn-saver/apps/webpnpm installCreate environment file from template:
# Copy the example file (note: .env files are gitignored, so we use env.example)
cp env.example .env.local
# Or copy the Whop template for minimal setup
cp env.development.template .env.localConfigure the following variables in .env.local:
# Environment
NODE_ENV=development
NEXT_PUBLIC_APP_URL=http://localhost:3000
# Database
DATABASE_URL=postgresql://churn_saver_dev:dev_password@localhost:5432/churn_saver_dev
# Whop Configuration
# Both variables are supported - NEXT_PUBLIC_WHOP_APP_ID is preferred
NEXT_PUBLIC_WHOP_APP_ID=your_development_app_id
WHOP_APP_ID=your_development_app_id # Optional alias
WHOP_API_KEY=your_development_api_key
WHOP_WEBHOOK_SECRET=your_development_webhook_secret
# Development Features
ALLOW_INSECURE_DEV=true
DEBUG_MODE=true
# Security
JWT_SECRET=your_development_jwt_secret_minimum_32_characters
ENCRYPTION_KEY=your_development_encryption_key_32_charactersNote: The codebase supports both NEXT_PUBLIC_WHOP_APP_ID and WHOP_APP_ID for backward compatibility. Use NEXT_PUBLIC_WHOP_APP_ID as the primary variable.
# Start PostgreSQL with Docker
docker run --name postgres-dev \
-e POSTGRES_DB=churn_saver_dev \
-e POSTGRES_USER=churn_saver_dev \
-e POSTGRES_PASSWORD=dev_password \
-p 5432:5432 \
-d postgres:14
# Wait for database to be ready
sleep 10# Create development database
createdb churn_saver_dev
# Create user (if needed)
createuser churn_saver_dev
psql -c "ALTER USER churn_saver_dev WITH PASSWORD 'dev_password';"# Run all pending migrations
pnpm run db:migrate
# Verify migration status
pnpm run db:migrate:status# Seed with sample data
pnpm run db:seedThe application uses PostgreSQL with connection pooling. Database connections are configured through the DATABASE_URL environment variable.
Key tables include:
users- User accounts and profilescompanies- Company/organization datacases- Churn recovery casesevents- Webhook events from Whopreminders- Scheduled reminders
# Run migrations
pnpm run db:migrate
# Rollback last migration
pnpm run db:rollback
# Create new migration
pnpm run db:migrate:create <migration_name>
# Check migration status
pnpm run db:migrate:status- Download from pgadmin.org
- Connect using development credentials
- Access at
postgresql://churn_saver_dev:dev_password@localhost:5432/churn_saver_dev
# Connect to database
psql -h localhost -p 5432 -U churn_saver_dev -d churn_saver_dev
# Useful commands
\l # List databases
\dt # List tables
\d table_name # Describe table
\q # QuitThe project follows a testing pyramid with comprehensive coverage:
- Unit Tests (70%): Component and utility testing
- Integration Tests (20%): API and database integration
- E2E Tests (10%): Critical user journey testing
# Run all unit tests
pnpm test
# Run tests in watch mode
pnpm test:watch
# Run specific test file
pnpm test -- test/unit/components/Button.test.ts
# Run tests matching a pattern
pnpm test -- -t "Button"# Run integration tests
pnpm test -- test/integration
# Run webhook tests specifically
pnpm test:webhooks
# Run core service tests
pnpm test:core# Run E2E tests (requires running dev server)
pnpm test:e2e
# Run E2E tests with UI
pnpm test:e2e:ui
# Run specific test
pnpm test:e2e -- tests/auth.spec.ts
# Run in headed mode (see browser)
pnpm test:e2e:headed# Run complete test suite
pnpm test
# Run with coverage
pnpm test:coverage
# Generate coverage report (HTML)
pnpm coverage:html
# Generate coverage report (LCOV)
pnpm coverage:lcovAvailable npm scripts:
{
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
"test:ci": "vitest run --coverage --reporter=verbose",
"test:e2e": "playwright test",
"test:e2e:ui": "playwright test --ui",
"test:e2e:headed": "playwright test --headed",
"test:webhooks": "vitest run --coverage --src src/lib/whop/ src/app/api/webhooks/ src/test/webhooks",
"test:core": "vitest run --coverage --src src/server/services/...",
"coverage:html": "vitest --coverage --reporter=html",
"coverage:lcov": "vitest --coverage --reporter=lcov"
}Tests use isolated database state. Each test suite:
- Creates fresh test database
- Runs migrations
- Seeds with test data
- Cleans up after completion
// test/unit/components/Button.test.tsx
import { describe, it, expect, vi } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import { Button } from '@/components/ui/button';
describe('Button', () => {
it('renders with correct text', () => {
render(<Button>Click me</Button>);
expect(screen.getByRole('button', { name: 'Click me' })).toBeInTheDocument();
});
it('handles click events', () => {
const handleClick = vi.fn();
render(<Button onClick={handleClick}>Click me</Button>);
fireEvent.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
});// test/integration/api/cases.test.ts
import { describe, it, expect } from 'vitest';
import { fetch } from 'undici';
describe('Cases API', () => {
it('creates new case', async () => {
const response = await fetch('http://localhost:3000/api/cases', {
method: 'POST',
headers: {
'Authorization': 'Bearer valid-token',
'Content-Type': 'application/json',
},
body: JSON.stringify({
userId: 'user-123',
companyId: 'company-456',
reason: 'churn_risk',
description: 'User at risk of churning'
}),
});
expect(response.status).toBe(201);
const data = await response.json();
expect(data).toHaveProperty('case');
expect(data.case.reason).toBe('churn_risk');
});
});Problem: Cannot connect to PostgreSQL
Symptoms:
- Migration commands fail
- Application throws connection errors
- Tests fail with database errors
Solutions:
# Check if PostgreSQL is running
brew services list | grep postgresql # macOS
sudo systemctl status postgresql # Linux
# Test connection manually
psql -h localhost -p 5432 -U churn_saver_dev -d churn_saver_dev
# Check DATABASE_URL format
echo $DATABASE_URL # Should be: postgresql://user:pass@host:port/db
# Reset database (development only)
pnpm run db:resetProblem: Webhooks not processing correctly
Symptoms:
- Events not appearing in dashboard
- Webhook endpoint returns errors
- Signature validation fails
Debug Steps:
# Test webhook endpoint directly
curl -X POST http://localhost:3000/api/webhooks/whop \
-H "Content-Type: application/json" \
-H "whop-signature: sha256=test_signature" \
-d '{"type":"user.created","data":{"user":{"id":"123"}}}'
# Check application logs
tail -f logs/app.log | grep webhook
# Use ngrok for external webhook testing
npx ngrok http 3000
# Update webhook URL in Whop dashboard to: https://xyz.ngrok.io/api/webhooks/whopProblem: Application cannot start due to missing env vars
Symptoms:
- Build fails with "process.env not defined"
- Runtime errors about undefined variables
- Authentication failures
Solutions:
# Check if .env.local exists
ls -la .env.local
# Validate required variables
grep -E "^(NEXT_PUBLIC_|WHOP_|DATABASE_URL|JWT_SECRET)" .env.local
# Restart development server after env changes
pnpm devProblem: TypeScript or build errors
Symptoms:
pnpm buildfails- IDE shows type errors
- Runtime JavaScript errors
Debug Commands:
# Type check only
pnpm type-check
# Lint code
pnpm lint
# Format code
pnpm format
# Clean and rebuild
rm -rf .next && pnpm buildProblem: Tests failing unexpectedly
Symptoms:
- Unit tests fail
- Integration tests timeout
- E2E tests cannot find elements
Debug Steps:
# Run specific failing test
pnpm test -- test/unit/components/Button.test.ts
# Run tests with verbose output
pnpm test:ci
# Debug integration test
pnpm test -- test/integration --reporter=verbose
# Run E2E in debug mode
pnpm test:e2e -- --debug# Start development server with Whop proxy
pnpm dev
# Server starts on http://localhost:3000
# API available at http://localhost:3000/api
# Whop iFrame context automatically configured via whop-proxyNote: The dev script automatically uses whop-proxy to configure the Whop iframe context. For detailed setup instructions, see Whop Development Proxy Setup.
The development server automatically reloads on file changes. No manual restart required.
Enable additional logging:
DEBUG=* pnpm devPORT=4000 pnpm dev # Starts on http://localhost:4000Monitor application logs during development:
# View logs in terminal (server must be running in another terminal)
tail -f logs/development.log
# Or check Docker logs (if using Docker)
docker logs -f churn-saver-postgresVerify server is running correctly:
# Health endpoint
curl http://localhost:3000/api/health
# Expected response:
# {"status":"ok","timestamp":"2023-12-25T10:00:00.000Z"}Server won't start:
- Check if port 3000 is available:
lsof -i :3000 - Verify all dependencies installed:
pnpm install - Check environment variables:
cat .env.local - Clear cache:
rm -rf .next
Database connection fails on startup:
- Ensure PostgreSQL is running
- Verify DATABASE_URL format
- Check database exists:
psql -l - Run migrations:
pnpm run db:migrate
Whop proxy issues:
- Verify Whop credentials in
.env.local - Check internet connection
- Restart with clean cache:
rm -rf node_modules/.cache - See Whop Development Proxy Setup for detailed troubleshooting
Getting Help
- Documentation: Check apps/web/docs/ for detailed guides
- Issues: Create GitHub issue with error details
- Community: Join development Slack/Discord
- Support: Contact development team
Last Updated: 2025-10-25 Version: 1.0.0