This guide covers everything needed to get a local development environment running.
Prerequisites
| Software | Version | Purpose |
|---|---|---|
| Node.js | 20.19+ | Server runtime |
| npm | 10.x+ | Package manager |
| Docker | 24.x+ | PostgreSQL container |
| Git | 2.x+ | Version control |
Installation
# Clone repository
git clone <repository-url>
cd poker-engine
# Install dependencies (root package plus the client and packages/* workspaces)
npm install
Environment Variables
Copy the example file and edit it:
cp .env.example .env
All environment variables are validated at startup by Zod (src/config/env-schema.ts, loaded by src/config/env.ts). The application will crash immediately on startup if any required variable is missing or invalid.
Required Variables
# Database
# These credentials match the postgres service in docker-compose.yml
DATABASE_URL="postgresql://postgres:password@localhost:5432/poker_engine?schema=public"
# Authentication (64+ characters; placeholder values such as change-this are rejected)
JWT_ACCESS_SECRET=<generate with: node -e "console.log(require('crypto').randomBytes(64).toString('hex'))">
JWT_REFRESH_SECRET=<generate with same command>
JWT_2FA_TEMP_SECRET=<generate with same command>
# Security (must be 32+ characters)
CSRF_SECRET=<generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))">
# CORS (comma-separated list of allowed origins)
CORS_ORIGINS=http://localhost:5173,http://localhost:3000
Optional Variables
# Server
NODE_ENV=development
PORT=3000
HOST=localhost
# JWT expiry (schema defaults; .env.example sets 15m and 7d)
JWT_ACCESS_EXPIRES_IN=5m
JWT_REFRESH_EXPIRES_IN=1d
# Password hashing
BCRYPT_ROUNDS=12
# Encryption key for sensitive data at rest: exactly 64 hex characters (required in production)
# Generate: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
ENCRYPTION_KEY=
# Redis (disabled by default)
REDIS_ENABLED=false
REDIS_URL=
# Sentry error tracking (disabled by default)
SENTRY_ENABLED=false
SENTRY_DSN=
# Development tools
QUERY_MONITOR=false # Detect N+1 queries
EVENT_TRACING=false # Trace WebSocket pipeline events
LOG_LEVEL=debug
What Is NOT in .env
Game settings, feature flags, SMTP configuration, and payment provider configuration are all managed through the Admin Panel (stored in the database). Do not look for these in .env.
Database Setup
# 1. Start PostgreSQL container
docker compose up -d postgres
# 2. Generate Prisma client (run after schema changes too)
npm run db:generate
# 3. Apply migrations
npm run db:migrate
# 4. Seed development data only (creates admin/admin123, player1-5/player123, bots and sample tables)
npm run db:seed
# 5. Open database GUI (optional)
npm run db:studio
For production or staging first install, do not run the development seed. Set ADMIN_INITIAL_PASSWORD to a unique password from your password manager, set NODE_ENV=production, apply migrations with npm run db:migrate:prod, and run npm run db:setup or start the server so the bootstrap service creates the initial admin account with that configured password.
Docker Services
The docker-compose.yml includes:
postgres— PostgreSQL 16 on port 5432redis— Redis 7 on port 6379 (only used whenREDIS_ENABLED=true)pgadmin— pgAdmin on port 5050mailhog— MailHog SMTP on port 1025, web UI on port 8025
Database Safety
Never run destructive commands against the dev database:
prisma migrate reset— drops all dataprisma db push --force-reset— same effect
Safe commands:
prisma migrate deploy— applies pending migrationsprisma validate— validates schema only
npm run db:push is intentionally disabled and exits with an error; schema changes go through npm run db:migrate.
If the database is accidentally wiped, run npm run db:seed to restore defaults.
Running Development Servers
# Backend (port 3000)
npm run dev
# Frontend (port 5173)
npm run dev:client
# Both together, in the background (status, stop and restart are also available)
./scripts/game.sh start
Verify Installation
# Backend health check
curl http://localhost:3000/health
# Run the test suite
npm test
# Type-check backend, scripts and all workspaces
npm run typecheck
IDE Configuration
VS Code (Recommended)
Install these extensions:
- ESLint — Linting
- Prettier — Formatting
- Prisma — Schema syntax highlighting
Recommended .vscode/settings.json:
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"typescript.tsdk": "node_modules/typescript/lib"
}
Development Tools
Logging
Set LOG_LEVEL=debug in .env for verbose server logs. The logger uses pino and outputs structured JSON in production, pretty-printed in development.
Query Monitor
Set QUERY_MONITOR=true to detect N+1 database queries during development. Set QUERY_MONITOR_VERBOSE=true for full query output and QUERY_MONITOR_THRESHOLD to change the threshold (default 10). npm run dev:query-monitor and npm run dev:query-monitor:verbose start the backend with these set.
Event Tracing
Set EVENT_TRACING=true to trace WebSocket events through the pipeline stages. Useful for debugging event processing order.
Prisma Studio
npm run db:studio
Opens a browser-based database GUI at http://localhost:5555.
Common Issues
"Cannot find module @prisma/client"
npm run db:generate
"Connection refused" to PostgreSQL
docker compose ps # Check if container is running
docker compose up -d postgres
docker compose logs postgres
WebSocket connection fails in browser
- Check CORS settings —
CORS_ORIGINSmust includehttp://localhost:5173 - Verify the Vite proxy in
client/vite.config.tsproxies/socket.iotohttp://localhost:3000
"Port 3000 already in use"
lsof -i :3000
kill -9 <PID>
TypeScript compilation errors after schema change
npm run db:generate
npm run typecheck
Back to Developer Guide