Setup

This guide covers everything needed to get a local development environment running.

Prerequisites

SoftwareVersionPurpose
Node.js20.19+Server runtime
npm10.x+Package manager
Docker24.x+PostgreSQL container
Git2.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 5432
  • redis — Redis 7 on port 6379 (only used when REDIS_ENABLED=true)
  • pgadmin — pgAdmin on port 5050
  • mailhog — 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 data
  • prisma db push --force-reset — same effect

Safe commands:

  • prisma migrate deploy — applies pending migrations
  • prisma 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

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

  1. Check CORS settings — CORS_ORIGINS must include http://localhost:5173
  2. Verify the Vite proxy in client/vite.config.ts proxies /socket.io to http://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

Try the live demo Pricing

Have questions about Poker Engine? We reply fast.