Skip to content

Local Development Setup

Complete guide for setting up the MMR SaaS Platform development environment on your local machine.

Prerequisites

Before starting, ensure you have the following installed:

  • Node.js 18.x or higher (Download)
  • PNPM 8.x or higher (package manager)
  • Git for version control
  • Docker (optional, recommended for quick setup)
  • MySQL 8.x or higher (if not using Docker)
  • Redis 7.x or higher (if not using Docker)

Verify Prerequisites

# Check Node.js version
node --version  # Should be v18.x or higher

# Check PNPM version
pnpm --version  # Should be 8.x or higher

# Check Git
git --version

# Check Docker (optional)
docker --version
docker-compose --version

Install PNPM

If you don't have PNPM installed:

# Using npm
npm install -g pnpm

# Or using Homebrew (macOS)
brew install pnpm

# Or using standalone script
curl -fsSL https://get.pnpm.io/install.sh | sh -

The fastest way to get started is using Docker for MySQL and Redis.

Step 1: Clone the Repository

git clone <repository-url>
cd MMR_SAAS_LAB

Step 2: Install Dependencies

pnpm install

This installs all dependencies for both backend and frontend applications using Turborepo's optimized installation.

Step 3: Setup Environment Variables

Backend Environment

# Copy example environment file
cp apps/backend/.env.example apps/backend/.env

Edit apps/backend/.env and configure:

# Server Configuration
NODE_ENV=development
PORT=3001
API_PREFIX=api

# Database (matches docker-compose.yml)
DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=root
DB_PASSWORD=password
DB_NAME=mmr_saas
DB_SYNCHRONIZE=false  # Always false - use migrations instead

# Redis (matches docker-compose.yml)
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=

# JWT Secrets (generate secure random strings)
# Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
JWT_SECRET=your-super-secret-jwt-key-change-this-in-production
JWT_EXPIRES_IN=15m
JWT_REFRESH_SECRET=your-super-secret-refresh-key-change-this-in-production
JWT_REFRESH_EXPIRY=7d

# CORS
CORS_ORIGIN=http://localhost:3000

# Rate Limiting
RATE_LIMIT_LOGIN_ATTEMPTS=5
RATE_LIMIT_LOCKOUT_MINUTES=15

Generate JWT Secrets:

# Generate JWT_SECRET
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

# Generate JWT_REFRESH_SECRET
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Frontend Environment

# Copy example environment file
cp apps/web/.env.example apps/web/.env.local

Edit apps/web/.env.local:

# Backend API URL
NEXT_PUBLIC_API_URL=http://localhost:3001/api

# Environment
NEXT_PUBLIC_ENV=development

Step 4: Start Docker Services

# Start MySQL and Redis
pnpm docker:up

# Verify services are running
docker ps

# You should see:
# - mmr-mysql (port 3306)
# - mmr-redis (port 6379)

Docker Compose Services: - MySQL 8.0 on port 3306 - Redis 7.x on port 6379

Step 5: Run Database Migrations

# Run all pending migrations
pnpm db:migrate

# Verify migrations
pnpm migration:show

This creates the necessary database tables (users, organizations, tenants, etc.).

Step 6: (Optional) Seed Test Data

# Seed database with sample data
pnpm db:seed

This creates: - Test organizations - Test users with different roles - Sample data for development

Step 7: Start Development Servers

# Start both frontend and backend
pnpm dev

# Or start separately:
pnpm dev:web    # Frontend only (http://localhost:3000)
pnpm dev:back   # Backend only (http://localhost:3001)

Access the application: - Frontend: http://localhost:3000 - Backend API: http://localhost:3001/api - API Health: http://localhost:3001/api/health

Step 8: Verify Setup

  1. Backend Health Check:

    curl http://localhost:3001/api/health
    # Should return: {"status":"ok"}
    

  2. Test Login:

  3. Open http://localhost:3000/login
  4. Use test credentials (if seeded)

  5. Check Logs:

  6. Backend logs appear in terminal
  7. Look for "Application is running on: http://localhost:3001"

Managing Docker Services

# Stop services
pnpm docker:down

# View logs
docker-compose logs -f mysql
docker-compose logs -f redis

# Restart services
docker-compose restart

# Remove all data (destructive!)
docker-compose down -v  # Removes volumes

Method 2: Native Installation

If you prefer not to use Docker, install MySQL and Redis natively.

Step 1: Install MySQL 8.x

On Ubuntu/Debian:

# Update package index
sudo apt update

# Install MySQL Server
sudo apt install mysql-server

# Secure installation
sudo mysql_secure_installation

# Start MySQL service
sudo systemctl start mysql
sudo systemctl enable mysql

# Verify installation
mysql --version

On macOS (Homebrew):

# Install MySQL
brew install mysql@8.0

# Start MySQL service
brew services start mysql@8.0

# Verify installation
mysql --version

On Windows:

Download and install MySQL 8.0 from MySQL Downloads.

Step 2: Install Redis 7.x

On Ubuntu/Debian:

# Install Redis
sudo apt install redis-server

# Start Redis service
sudo systemctl start redis-server
sudo systemctl enable redis-server

# Verify installation
redis-cli ping  # Should return "PONG"

On macOS (Homebrew):

# Install Redis
brew install redis

# Start Redis service
brew services start redis

# Verify installation
redis-cli ping  # Should return "PONG"

On Windows:

Download Redis for Windows from Microsoft Archive or use WSL2.

Step 3: Configure MySQL Database

# Login to MySQL as root
sudo mysql -u root -p

# Create database
CREATE DATABASE mmr_saas CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

# Create user (use a strong password in production)
CREATE USER 'mmr_user'@'localhost' IDENTIFIED BY 'your_secure_password';

# Grant privileges
GRANT ALL PRIVILEGES ON mmr_saas.* TO 'mmr_user'@'localhost';
FLUSH PRIVILEGES;

# Exit MySQL
EXIT;

# Test connection
mysql -u mmr_user -p mmr_saas

Step 4: Configure Redis

Redis works out of the box with default configuration for development.

Optional: Enable password protection

Edit Redis config:

# Find config file location
redis-cli CONFIG GET dir

# Edit config (Ubuntu/Debian)
sudo nano /etc/redis/redis.conf

# Uncomment and set password
requirepass your_redis_password

# Restart Redis
sudo systemctl restart redis-server

Step 5: Update Environment Variables

Update apps/backend/.env with your MySQL credentials:

DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=mmr_user
DB_PASSWORD=your_secure_password
DB_NAME=mmr_saas

REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=your_redis_password  # If you set one

Step 6: Follow Docker Steps 1, 2, 5, 6, 7

Complete the remaining setup steps from the Docker method: - Clone repository and install dependencies (Steps 1-2) - Run migrations and seed data (Steps 5-6) - Start development servers (Step 7)


Install these VS Code extensions for the best development experience:

  1. ESLint (dbaeumer.vscode-eslint) - JavaScript/TypeScript linting
  2. Prettier (esbenp.prettier-vscode) - Code formatting
  3. Tailwind CSS IntelliSense (bradlc.vscode-tailwindcss) - Tailwind autocomplete
  4. TypeScript Vue Plugin (Volar) - Not needed
  5. Prisma - Not needed (using TypeORM)
  6. REST Client (humao.rest-client) - Test API endpoints
  7. GitLens (eamodio.gitlens) - Git integration
  8. Auto Rename Tag (formulahendry.auto-rename-tag) - HTML/JSX tags
  9. Path Intellisense (christian-kohler.path-intellisense) - File path autocomplete
  10. Better Comments (aaron-bond.better-comments) - Highlighted comments

VS Code Settings

Create .vscode/settings.json in the project root:

{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "typescript.tsdk": "node_modules/typescript/lib",
  "typescript.enablePromptUseWorkspaceTsdk": true,
  "tailwindCSS.experimental.classRegex": [
    ["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
    ["cn\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"]
  ]
}

Launch Configuration (Debugging)

Create .vscode/launch.json:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Backend",
      "runtimeExecutable": "pnpm",
      "runtimeArgs": ["dev:back"],
      "skipFiles": ["<node_internals>/**"],
      "cwd": "${workspaceFolder}"
    },
    {
      "type": "node",
      "request": "launch",
      "name": "Debug Frontend",
      "runtimeExecutable": "pnpm",
      "runtimeArgs": ["dev:web"],
      "skipFiles": ["<node_internals>/**"],
      "cwd": "${workspaceFolder}"
    }
  ]
}

Troubleshooting

Port Already in Use

Error: EADDRINUSE: address already in use :::3000 or :::3001

Solution:

# Find process using the port
lsof -i :3000  # Frontend
lsof -i :3001  # Backend

# Kill the process
kill -9 <PID>

# Or change port in .env files

Database Connection Failed

Error: ER_ACCESS_DENIED_ERROR or ECONNREFUSED

Solutions:

  1. Verify MySQL is running:

    # Docker
    docker ps | grep mysql
    
    # Native
    sudo systemctl status mysql  # Linux
    brew services list | grep mysql  # macOS
    

  2. Check credentials in .env:

  3. DB_USERNAME, DB_PASSWORD, DB_NAME must match MySQL user

  4. Test connection manually:

    mysql -h localhost -u mmr_user -p mmr_saas
    

Redis Connection Failed

Error: ECONNREFUSED 127.0.0.1:6379

Solutions:

  1. Verify Redis is running:

    # Docker
    docker ps | grep redis
    
    # Native
    redis-cli ping  # Should return "PONG"
    

  2. Start Redis:

    # Docker
    docker-compose up -d redis
    
    # Native Linux
    sudo systemctl start redis-server
    
    # Native macOS
    brew services start redis
    

Migration Errors

Error: Migration XYZ has already been executed

Solution:

# Show migration status
pnpm migration:show

# Revert last migration if needed
pnpm migration:revert

# Re-run migrations
pnpm db:migrate

PNPM Install Fails

Error: ENOENT: no such file or directory

Solution:

# Clear PNPM cache
pnpm store prune

# Remove node_modules and lockfile
rm -rf node_modules apps/*/node_modules packages/*/node_modules
rm pnpm-lock.yaml

# Reinstall
pnpm install

Turbo Cache Issues

Error: Build fails with cached errors

Solution:

# Clear Turbo cache
pnpm clean

# Or manually
rm -rf node_modules/.cache/turbo

# Rebuild
pnpm build

Frontend Build Errors (Type Errors)

Error: TypeScript type errors during build

Solution:

# Navigate to frontend
cd apps/web

# Check for type errors
pnpm type-check

# If shared types changed, rebuild packages
cd ../..
pnpm build --filter=@mmr/types
pnpm build --filter=@mmr/schemas

JWT Errors (Invalid Signature)

Error: JsonWebTokenError: invalid signature

Solution: - Ensure JWT_SECRET in .env matches the secret used to generate tokens - Regenerate JWT secrets if you changed them:

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
- Clear browser cookies and Redis cache - Re-login to get new tokens


Next Steps

After successful setup:

  1. Read the Contributing Guide: CONTRIBUTING.md
  2. Understand the Architecture: ARCHITECTURE.md
  3. Learn the Git Workflow: GIT_WORKFLOW.md
  4. Explore the AI Agent System: .claude/agents/README.md
  5. Start building features!

Quick Reference

Common Commands

# Development
pnpm dev              # Start both frontend & backend
pnpm dev:web          # Frontend only
pnpm dev:back         # Backend only

# Build
pnpm build            # Build all apps
pnpm build:web        # Build frontend
pnpm build:back       # Build backend

# Production
pnpm start            # Start both (production mode)
pnpm start:web        # Start frontend (production)
pnpm start:back       # Start backend (production)

# Database
pnpm db:migrate       # Run migrations
pnpm db:seed          # Seed test data
pnpm migration:generate  # Generate new migration
pnpm migration:show   # Show migration status

# Docker
pnpm docker:up        # Start MySQL + Redis
pnpm docker:down      # Stop services

# Testing
pnpm test             # Run all tests
pnpm test:e2e         # Run E2E tests
pnpm test:cov         # Coverage report

# Code Quality
pnpm lint             # Lint all code
pnpm format           # Format with Prettier
pnpm type-check       # TypeScript type checking

# Cleanup
pnpm clean            # Remove build artifacts

Default Ports

  • Frontend (Next.js): http://localhost:3000
  • Backend (NestJS): http://localhost:3001
  • MySQL: localhost:3306
  • Redis: localhost:6379

Default Credentials (After Seeding)

Check apps/backend/src/database/seeds/ for test user credentials.


Version: 2.0.0 | Last Updated: 2026-06-20