Local Development Setup¶
This guide walks you through setting up Changemaker Lite V2 for local development on your machine.
Overview¶
Changemaker Lite V2 supports two development approaches:
- Docker-based development - Run API and Admin in containers (recommended for consistency)
- Local npm development - Run services directly on your host machine (faster hot reload)
This guide covers both approaches. Choose the one that fits your workflow.
Prerequisites¶
Required Software¶
Node.js and npm¶
- Node.js 20.x LTS or higher
- npm 10.x or higher
# Check versions
node --version # Should be v20.x.x or higher
npm --version # Should be 10.x.x or higher
Installation: - Download from nodejs.org - Or use nvm for version management:
Docker and Docker Compose¶
- Docker Engine 24.x or higher
- Docker Compose 2.x or higher (included with Docker Desktop)
# Check versions
docker --version # Should be 24.x.x or higher
docker compose version # Should be 2.x.x or higher
Installation: - Docker Desktop: docker.com/get-started - Linux: docs.docker.com/engine/install
Git¶
- Git 2.30 or higher
Installation: - Download from git-scm.com - Or use package manager (apt, brew, etc.)
Optional Tools¶
PostgreSQL Client Tools¶
Useful for database inspection and debugging:
# Ubuntu/Debian
sudo apt install postgresql-client
# macOS
brew install postgresql@16
# Check installation
psql --version
Redis CLI¶
For cache/queue debugging:
# Ubuntu/Debian
sudo apt install redis-tools
# macOS
brew install redis
# Check installation
redis-cli --version
Visual Studio Code¶
Recommended IDE with excellent TypeScript support:
- Download from code.visualstudio.com
- See IDE Setup section for recommended extensions
System Requirements¶
Minimum: - 8 GB RAM - 20 GB free disk space - 2 CPU cores
Recommended: - 16 GB RAM - 50 GB free disk space - 4+ CPU cores
Repository Setup¶
Clone Repository¶
# Clone the repository
git clone <repo-url> changemaker.lite
cd changemaker.lite
# Checkout v2 branch
git checkout v2
# Verify branch
git branch --show-current
# Output: v2
Repository Structure¶
After cloning, your directory structure should look like:
changemaker.lite/
├── api/ # Express.js + Fastify backend
├── admin/ # React frontend
├── configs/ # Monitoring configs (Prometheus, Grafana)
├── nginx/ # Reverse proxy configuration
├── scripts/ # Utility scripts
├── docker-compose.yml # V2 orchestration
├── .env.example # Environment template
└── V2_PLAN.md # Development roadmap
Verify Files¶
Check that key files exist:
If any files are missing, ensure you're on the v2 branch.
Environment Configuration¶
Create .env File¶
Copy the example environment file:
Configure Essential Variables¶
Open .env in your editor and set the following critical variables:
Database Passwords¶
# PostgreSQL password (use a strong password)
V2_POSTGRES_PASSWORD=your_strong_password_here
# Redis password (use a strong password)
REDIS_PASSWORD=your_redis_password_here
JWT Secrets¶
Generate secure random secrets:
# Generate secrets (run these commands separately)
openssl rand -hex 32 # For JWT_ACCESS_SECRET
openssl rand -hex 32 # For JWT_REFRESH_SECRET
openssl rand -hex 32 # For ENCRYPTION_KEY
Add to .env:
# JWT secrets (use different values for each!)
JWT_ACCESS_SECRET=<output from first command>
JWT_REFRESH_SECRET=<output from second command>
ENCRYPTION_KEY=<output from third command>
IMPORTANT: All three secrets must be different values!
Email Configuration (Development)¶
For development, use MailHog to capture emails locally:
# Email test mode (sends to MailHog instead of real SMTP)
EMAIL_TEST_MODE=true
# MailHog SMTP settings
EMAIL_SMTP_HOST=localhost
EMAIL_SMTP_PORT=1025
EMAIL_SMTP_SECURE=false
EMAIL_FROM_ADDRESS=noreply@cmlite.org
EMAIL_FROM_NAME=Changemaker Lite
Optional Features¶
Enable optional features as needed:
# Media Manager (video library)
ENABLE_MEDIA_FEATURES=true
# Listmonk newsletter sync
LISTMONK_SYNC_ENABLED=false # Enable later if needed
# API ports (defaults work for most setups)
API_PORT=4000
ADMIN_PORT=3000
MEDIA_API_PORT=4100
Complete .env Template¶
Here's a minimal .env for local development:
# Database
V2_POSTGRES_PASSWORD=your_strong_password
DATABASE_URL=postgresql://changemaker_v2:your_strong_password@localhost:5433/changemaker_v2_db
# Redis
REDIS_PASSWORD=your_redis_password
REDIS_URL=redis://:your_redis_password@localhost:6379
# JWT
JWT_ACCESS_SECRET=<32-byte hex from openssl>
JWT_REFRESH_SECRET=<32-byte hex from openssl>
ENCRYPTION_KEY=<32-byte hex from openssl>
# Email (MailHog for dev)
EMAIL_TEST_MODE=true
EMAIL_SMTP_HOST=localhost
EMAIL_SMTP_PORT=1025
EMAIL_SMTP_SECURE=false
EMAIL_FROM_ADDRESS=noreply@cmlite.org
EMAIL_FROM_NAME=Changemaker Lite
# Ports
API_PORT=4000
ADMIN_PORT=3000
MEDIA_API_PORT=4100
# Features
ENABLE_MEDIA_FEATURES=true
LISTMONK_SYNC_ENABLED=false
# Node environment
NODE_ENV=development
Verify Configuration¶
Check that required variables are set:
grep -E '^(V2_POSTGRES_PASSWORD|REDIS_PASSWORD|JWT_ACCESS_SECRET|JWT_REFRESH_SECRET|ENCRYPTION_KEY)=' .env
You should see 5 lines with non-empty values.
Database Setup¶
Start Database Services¶
Start PostgreSQL and Redis containers:
Wait for databases to initialize (first run takes 30-60 seconds):
# Watch logs
docker compose logs -f v2-postgres redis
# Look for:
# v2-postgres: "database system is ready to accept connections"
# redis: "Ready to accept connections"
# Press Ctrl+C to exit logs
Verify Database Connection¶
Test PostgreSQL connection:
You should see PostgreSQL version information.
Test Redis connection:
Install API Dependencies¶
Expected output: - Installs ~300+ packages - May show peer dependency warnings (safe to ignore) - Should complete without errors
Run Database Migrations¶
Apply Prisma migrations to create database schema:
Expected output:
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "changemaker_v2_db"
20 migrations found in prisma/migrations
Applying migration `20260101000000_init`
Applying migration `20260105000000_add_campaigns`
...
All migrations have been successfully applied.
Seed Database¶
Populate database with initial data (admin user, settings, etc.):
Expected output:
Running seed command `tsx prisma/seed.ts` ...
Seeding database...
Created default settings
Created admin user: admin@example.com
Created 10 sample blocks
...
Seed completed successfully
Default Admin Credentials:
- Email: admin@example.com
- Password: Admin123!
- Change this password immediately after first login!
Verify Database Schema¶
Open Prisma Studio to browse the database:
This opens a browser at http://localhost:5555 showing:
- 30+ tables (User, Campaign, Location, Shift, etc.)
- Seeded data (1 admin user, settings, blocks)
Press Ctrl+C to close Prisma Studio when done.
Return to Project Root¶
Starting Services¶
You have two options for running the development servers:
Option 1: Docker-based Development (Recommended)¶
Run API and Admin in Docker containers with volume mounts for hot reload:
# Start API and Admin containers
docker compose up -d api admin
# Optional: Start MailHog for email testing
docker compose up -d mailhog
# Optional: Start Media API
docker compose up -d media-api
Watch logs:
# All services
docker compose logs -f api admin
# Just API
docker compose logs -f api
# Just Admin
docker compose logs -f admin
Verify services started:
You should see:
- api - running on port 4000
- admin - running on port 3000
- v2-postgres - running on port 5433
- redis - running on port 6379
- mailhog - running on port 8025 (if started)
Hot Reload in Docker:
Volume mounts automatically sync code changes:
- API: tsx watch restarts server on file changes
- Admin: Vite HMR updates browser without full reload
Option 2: Local npm Development¶
Run services directly on your host machine (faster hot reload):
Terminal 1: API Server¶
Expected output:
> api@2.0.0 dev
> tsx watch src/server.ts
Server running on port 4000
Database connected
Redis connected
BullMQ worker started
Terminal 2: Admin Server¶
Expected output:
> admin@2.0.0 dev
> vite
VITE v5.x.x ready in 500 ms
➜ Local: http://localhost:3000/
➜ Network: use --host to expose
Terminal 3: Media API (Optional)¶
Expected output:
> api@2.0.0 dev:media
> tsx watch src/media-server.ts
Media API server running on port 4100
Database connected
Background Services¶
You still need Docker for PostgreSQL, Redis, and MailHog:
Which Approach to Use?¶
Use Docker-based development if: - You want consistent environment across team - You're new to the project - You prefer simpler setup
Use local npm development if: - You want faster hot reload (especially for frontend) - You're actively developing API changes - You prefer direct access to Node.js processes
You can mix approaches: - Run API in Docker, Admin locally - Run databases in Docker, both API/Admin locally
Verifying Setup¶
Health Check Endpoints¶
Test that services are responding:
# API health check
curl http://localhost:4000/health
# Expected: {"status":"ok","timestamp":"2026-02-13T..."}
# Admin (open in browser)
open http://localhost:3000
# Or visit manually: http://localhost:3000
# Media API health check (if enabled)
curl http://localhost:4100/health
# Expected: {"status":"ok","timestamp":"2026-02-13T..."}
Test Authentication¶
Test login endpoint:
curl -X POST http://localhost:4000/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "admin@example.com",
"password": "Admin123!"
}'
Expected response:
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": 1,
"email": "admin@example.com",
"role": "SUPER_ADMIN"
}
}
Login to Admin GUI¶
- Open http://localhost:3000 in browser
- Login with:
- Email:
admin@example.com - Password:
Admin123! - You should be redirected to
/app(admin dashboard) - Change password immediately:
- Click user menu (top right)
- Settings → Change Password
- Set new password (12+ chars, uppercase, lowercase, digit)
Verify Database Connection¶
Check that API can query database:
Expected response:
{
"users": [
{
"id": 1,
"email": "admin@example.com",
"role": "SUPER_ADMIN",
...
}
],
"total": 1,
"page": 1,
"limit": 50
}
Test Email Capture (MailHog)¶
- Open http://localhost:8025 in browser
- You should see MailHog web UI
- Trigger a test email (e.g., shift signup)
- Email appears in MailHog inbox
IDE Setup¶
Visual Studio Code¶
Recommended IDE with excellent TypeScript/React support.
Recommended Extensions¶
Install these extensions for best developer experience:
Essential:
- ESLint (dbaeumer.vscode-eslint) - Linting
- Prettier (esbenp.prettier-vscode) - Code formatting
- Prisma (Prisma.prisma) - Prisma schema support
- TypeScript Vue Plugin (Volar) (Vue.volar) - Vue/JSX support
Highly Recommended:
- GitLens (eamodio.gitlens) - Git insights
- Docker (ms-azuretools.vscode-docker) - Docker management
- Thunder Client (rangav.vscode-thunder-client) - API testing
- Error Lens (usernamehw.errorlens) - Inline errors
- Auto Rename Tag (formulahendry.auto-rename-tag) - HTML/JSX tag pairs
- Path Intellisense (christian-kohler.path-intellisense) - Path autocomplete
Optional:
- Tailwind CSS IntelliSense (bradlc.vscode-tailwindcss) - Tailwind support
- DotENV (mikestead.dotenv) - .env syntax highlighting
- Import Cost (wix.vscode-import-cost) - Bundle size info
Workspace Settings¶
Create .vscode/settings.json in project root:
{
// Editor
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"editor.tabSize": 2,
"editor.insertSpaces": true,
// Files
"files.eol": "\n",
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
// TypeScript
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
"typescript.preferences.importModuleSpecifier": "relative",
// Prisma
"[prisma]": {
"editor.defaultFormatter": "Prisma.prisma"
},
// ESLint
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
// Search exclusions (performance)
"search.exclude": {
"**/node_modules": true,
"**/dist": true,
"**/build": true,
"**/.git": true,
"**/coverage": true
},
// File associations
"files.associations": {
"*.css": "css",
".env*": "dotenv"
}
}
Launch Configuration¶
Create .vscode/launch.json for debugging:
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug API",
"type": "node",
"request": "launch",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"cwd": "${workspaceFolder}/api",
"console": "integratedTerminal",
"skipFiles": ["<node_internals>/**"],
"envFile": "${workspaceFolder}/.env"
},
{
"name": "Debug Admin (Chrome)",
"type": "chrome",
"request": "launch",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}/admin/src",
"sourceMapPathOverrides": {
"webpack:///./src/*": "${webRoot}/*"
}
},
{
"name": "Debug Media API",
"type": "node",
"request": "launch",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev:media"],
"cwd": "${workspaceFolder}/api",
"console": "integratedTerminal",
"skipFiles": ["<node_internals>/**"],
"envFile": "${workspaceFolder}/.env"
}
]
}
Workspace File¶
Create changemaker-lite.code-workspace:
{
"folders": [
{
"name": "Root",
"path": "."
},
{
"name": "API",
"path": "api"
},
{
"name": "Admin",
"path": "admin"
}
],
"settings": {
// Workspace-level settings (inherits from .vscode/settings.json)
}
}
Open workspace: code changemaker-lite.code-workspace
Other IDEs¶
WebStorm / IntelliJ IDEA¶
- Built-in TypeScript support
- Built-in Prisma plugin
- Configure ESLint/Prettier in Preferences → Languages & Frameworks
Neovim / Vim¶
- Use LSP with
typescript-language-server - Prisma LSP:
@prisma/language-server - ESLint/Prettier via null-ls or ALE
Troubleshooting¶
Port Conflicts¶
Problem: Port already in use errors
Solution 1: Find and kill the process using the port
Solution 2: Use different ports in .env
Database Connection Errors¶
Problem: API cannot connect to PostgreSQL
Solution 1: Verify PostgreSQL is running
Solution 2: Check DATABASE_URL in .env
# Should match your password and port
DATABASE_URL=postgresql://changemaker_v2:your_password@localhost:5433/changemaker_v2_db
Solution 3: Restart PostgreSQL container
docker compose restart v2-postgres
docker compose logs -f v2-postgres
# Wait for "ready to accept connections"
Redis Connection Errors¶
Problem: API cannot connect to Redis
Solution 1: Verify Redis is running
Solution 2: Check REDIS_URL and password
# Should match your password
REDIS_URL=redis://:your_redis_password@localhost:6379
REDIS_PASSWORD=your_redis_password
Solution 3: Test Redis connection directly
Migration Errors¶
Problem: Prisma migration fails
Solution 1: Reset database (DEVELOPMENT ONLY)
Solution 2: Force deploy migrations
Solution 3: Check migration history
npm Install Failures¶
Problem: npm install fails with permission errors
Solution 1: Clear npm cache
Solution 2: Use correct Node.js version
Solution 3: Check disk space
Hot Reload Not Working¶
Problem: Code changes don't trigger reload
Solution 1 (Docker): Verify volume mounts in docker-compose.yml
Solution 2 (Local): Restart dev server
Solution 3 (Admin/Vite): Clear Vite cache
Admin Build Errors¶
Problem: TypeScript errors on build
Solution 1: Type-check without emit
Solution 2: Update type definitions
Solution 3: Check tsconfig.json
Docker Container Crashes¶
Problem: API/Admin container exits immediately
Solution 1: Check logs
Solution 2: Verify .env file exists
Solution 3: Rebuild containers
Browser CORS Errors¶
Problem: Admin cannot call API (CORS errors in browser console)
Solution 1: Check CORS_ORIGIN in .env
Solution 2: Verify API_URL in admin
For Docker-based API, admin vite.config.ts proxy should work automatically.
For local API, ensure VITE_API_URL is NOT set (defaults to localhost:4000).
Solution 3: Clear browser cache
- Open DevTools → Network tab → Disable cache
- Hard reload (Cmd+Shift+R / Ctrl+Shift+R)
Hot Reload¶
API Hot Reload (tsx watch)¶
API uses tsx watch for automatic restart on file changes:
What triggers reload:
- Changes to .ts files in src/
- Changes to .prisma files (after running migrate)
What does NOT trigger reload:
- Changes to .env (restart manually)
- Changes to node_modules/ (reinstall packages)
Manual restart:
Admin Hot Reload (Vite HMR)¶
Admin uses Vite's Hot Module Replacement (HMR):
What triggers HMR:
- Changes to .tsx / .ts files
- Changes to .css files
- Changes to imported assets
HMR Behavior: - Component changes: Updates without full reload - Hook changes: May require full reload - Route changes: Full reload
Force full reload:
- Press r in terminal running Vite
- Or refresh browser (Cmd+R / Ctrl+R)
Docker Hot Reload¶
Docker volume mounts enable hot reload in containers:
# docker-compose.yml
api:
volumes:
- ./api:/app # Syncs code changes
- /app/node_modules # Preserves container's node_modules
Same reload behavior as local: - API: tsx watch restarts on .ts changes - Admin: Vite HMR updates browser
Performance note: - macOS/Windows: Volume mounts slightly slower than Linux - For intensive development, consider running locally instead
Debugging¶
API Debugging (VSCode)¶
- Open VSCode
- Open Run and Debug panel (Cmd+Shift+D / Ctrl+Shift+D)
- Select "Debug API" configuration
- Press F5 to start debugging
- Set breakpoints by clicking line numbers
- Trigger API endpoint to hit breakpoint
Debugging features: - Step through code (F10, F11) - Inspect variables - Evaluate expressions in Debug Console - Call stack navigation
Frontend Debugging (Chrome DevTools)¶
- Open Admin in Chrome: http://localhost:3000
- Open DevTools (F12 / Cmd+Option+I)
- Go to Sources tab
- Find your component in file tree (webpack://./src/)
- Set breakpoints by clicking line numbers
- Interact with UI to trigger breakpoint
React DevTools: - Install React DevTools browser extension - Inspect component tree - View/edit props and state - Profile component renders
Zustand DevTools¶
Enable Redux DevTools for Zustand stores:
// Already configured in auth.store.ts and canvass.store.ts
import { devtools } from 'zustand/middleware';
export const useAuthStore = create<AuthState>()(
devtools(
(set, get) => ({
// ... store implementation
}),
{ name: 'AuthStore' }
)
);
Usage: 1. Install Redux DevTools browser extension 2. Open extension 3. Select "AuthStore" or "CanvassStore" 4. See action history and state changes
Common Workflows¶
Starting Fresh Development Day¶
# 1. Pull latest changes
git pull origin v2
# 2. Check for dependency updates
cd api && npm install && cd ..
cd admin && npm install && cd ..
# 3. Apply any new migrations
cd api && npx prisma migrate deploy && cd ..
# 4. Start services
docker compose up -d v2-postgres redis mailhog
# Either:
docker compose up -d api admin # Docker approach
# Or:
cd api && npm run dev # Terminal 1 (local approach)
cd admin && npm run dev # Terminal 2 (local approach)
# 5. Open browser
open http://localhost:3000
Feature Development Workflow¶
# 1. Create feature branch
git checkout -b feature/my-new-feature
# 2. Start development servers (see above)
# 3. Make changes
# - Edit code
# - Test in browser
# - Check API responses
# 4. Type-check
cd api && npx tsc --noEmit && cd ..
cd admin && npx tsc --noEmit && cd ..
# 5. Run tests (when available)
# cd api && npm test && cd ..
# cd admin && npm test && cd ..
# 6. Commit changes
git add .
git commit -m "feat: add new feature"
# 7. Push and create PR
git push origin feature/my-new-feature
# Open PR on GitHub/GitLab
Database Schema Changes¶
# 1. Edit Prisma schema
cd api
vi prisma/schema.prisma # Add/modify models
# 2. Create migration
npx prisma migrate dev --name add_new_field
# 3. Migration auto-applies to dev database
# Check generated SQL in prisma/migrations/
# 4. Update seed if needed
vi prisma/seed.ts
# 5. Test migration on clean database
npx prisma migrate reset # WARNING: Deletes data
# Re-run migrations + seed
# 6. Commit migration files
git add prisma/migrations/ prisma/schema.prisma
git commit -m "feat(db): add new field to User model"
Bug Fixing Workflow¶
# 1. Reproduce bug locally
# - Follow steps from bug report
# - Check browser console
# - Check API logs (docker compose logs -f api)
# 2. Add logging to isolate issue
# api/src/modules/foo/foo.service.ts
logger.error('Bug context', { data });
# 3. Set breakpoints (VSCode debug)
# - Run "Debug API" configuration
# - Trigger bug
# - Step through code
# 4. Fix bug
# - Make code changes
# - Hot reload picks up changes
# - Test fix
# 5. Verify fix
# - Re-test original bug steps
# - Check related functionality
# - Type-check: npx tsc --noEmit
# 6. Commit fix
git add .
git commit -m "fix: resolve issue with user login"
Switching Between Docker and Local¶
From Docker to Local:
# 1. Stop Docker services
docker compose stop api admin
# 2. Keep databases running
docker compose ps v2-postgres redis mailhog
# Should show running
# 3. Start local dev servers
cd api && npm run dev # Terminal 1
cd admin && npm run dev # Terminal 2
From Local to Docker:
# 1. Stop local dev servers
# Press Ctrl+C in both terminals
# 2. Start Docker services
docker compose up -d api admin
# 3. Watch logs
docker compose logs -f api admin
Next Steps¶
After completing local setup:
- Read Development Guides:
- NPM Commands Reference - All package.json scripts
- Docker Workflow - Advanced Docker development
-
Database Migrations - Schema change workflow
-
Understand Architecture:
- API Architecture - Backend organization
- Frontend Architecture - React app structure
-
Database Schema - Data models
-
Learn Code Patterns:
- TypeScript Guide - TypeScript best practices
- Code Style Guide - Coding standards
-
Testing Guide - Test writing
-
Start Contributing:
- Git Workflow - Branching and commits
- Contributing Guide - Contribution process
- V2 Development Plan - Roadmap and phases
Related Documentation¶
- Deployment: Docker Compose Deployment
- Configuration: Environment Variables
- Database: Migrations Guide
- Testing: Testing Strategy
- Debugging: Debugging Guide
Getting Help¶
Documentation: - This guide for setup issues - Troubleshooting for common problems - FAQ for quick answers
Community: - GitHub Issues for bug reports - GitHub Discussions for questions - Project README for contact info
Logs:
- API logs: docker compose logs -f api
- Admin logs: docker compose logs -f admin
- Database logs: docker compose logs -f v2-postgres
Summary¶
You now have: - ✅ Prerequisites installed (Node.js, Docker, Git) - ✅ Repository cloned and on v2 branch - ✅ Environment configured (.env file) - ✅ Database initialized (migrations + seed) - ✅ Services running (API + Admin + databases) - ✅ IDE configured (VSCode with extensions) - ✅ Admin GUI accessible (http://localhost:3000)
Test your setup: 1. Login to Admin GUI (admin@example.com / Admin123!) 2. Navigate to Users page (/app/users) 3. See yourself in the users table 4. Check MailHog (http://localhost:8025) for welcome email
Ready to develop! Choose a task from V2_PLAN.md Phase 15 or create a feature branch.