Skip to main content

Environment Configuration Guide

Overview

The TVL Platform supports multiple deployment scenarios with different development environments and database configurations. This guide covers:

  1. Development Environment Setup - WSL, DevContainer, and optional AI tools
  2. Secrets Management - Doppler for secure credential management
  3. Database Configuration - Docker PostgreSQL vs Remote Supabase
  4. Migration Strategies - Safe deployment workflows

Quick Links:


Development Environment Setup

System Requirements

  • Operating System: Windows 10/11 with WSL2, macOS, or Linux
  • WSL2 (Windows only): Ubuntu 20.04+ or Debian
  • Docker Desktop: 4.30+ with WSL2 backend (Windows) or native (macOS/Linux)
  • Node.js: 20 LTS (managed via DevContainer)
  • IDE: VS Code, Cursor, or compatible editor with DevContainer support

Critical Performance Consideration (Windows + WSL Users)

⚠️ IMPORTANT: Repository location dramatically affects performance on Windows with WSL.

Repository LocationPerformanceRecommendation
WSL Filesystem (~/projects/)10-20x fasterREQUIRED for development
Windows Filesystem (/mnt/c/)❌ 10-20x slowerDO NOT USE

Performance Impact:

OperationWindows FS (/mnt/c/)WSL FS (~/projects/)Improvement
pnpm install~8 min~45 sec10.6x faster
git status~2 sec~0.1 sec20x faster
Hot reload~5 sec~0.5 sec10x faster
TypeScript compile~15 sec~3 sec5x faster

Setup Instructions (Windows Only):

# 1. Open WSL terminal (Ubuntu)
wsl

# 2. Create projects directory
cd ~
mkdir -p projects
cd projects

# 3. Clone or move repository
# Option A: Clone fresh
git clone https://github.com/your-org/the-villa-life.git
cd the-villa-life

# Option B: Move existing repository
cp -r /mnt/c/GitHub/the-villa-life ./
cd the-villa-life

# 4. Verify git status
git status # Should show clean working tree

# 5. Update git safe directory
git config --global --add safe.directory ~/projects/the-villa-life

# 6. Open in VS Code/Cursor from WSL location
code . # or: cursor .

Verify Performance:

# Test git performance (should be < 0.1 sec)
time git status

# Test pnpm performance (after DevContainer setup)
time pnpm install --frozen-lockfile
# Expected: < 60 seconds

DevContainer Setup

The TVL Platform uses DevContainers for consistent development environments. All developers get:

  • ✅ Node.js 20 LTS
  • ✅ pnpm 10.19.0
  • ✅ PostgreSQL client
  • ✅ Git
  • ✅ GitHub CLI
  • ✅ Shared tool versions (no "works on my machine" issues)

Initial Setup:

  1. Install Prerequisites:

    # Install Docker Desktop
    # Windows: https://www.docker.com/products/docker-desktop
    # macOS: https://www.docker.com/products/docker-desktop
    # Linux: https://docs.docker.com/engine/install/

    # Install VS Code or Cursor
    # VS Code: https://code.visualstudio.com/
    # Cursor: https://cursor.sh/

    # Install Dev Containers extension
    # In VS Code/Cursor: Ctrl+Shift+X → Search "Dev Containers" → Install
  2. Enable Docker WSL Integration (Windows Only):

    1. Open Docker Desktop
    2. Settings → Resources → WSL Integration
    3. Enable: ☑ Ubuntu (or your WSL distro)
    4. Apply & Restart
  3. Open Project in DevContainer:

    # Method 1: VS Code/Cursor GUI
    # - Open project folder
    # - Press F1
    # - Type: "Dev Containers: Reopen in Container"
    # - Wait for container to build (5-10 minutes first time)

    # Method 2: Command line
    cd ~/projects/the-villa-life # Use WSL path!
    code . # or: cursor .
    # Then: F1 → "Dev Containers: Reopen in Container"
  4. Verify Environment:

    # Inside DevContainer terminal (Ctrl+`)

    # Check Node.js
    node --version # Expected: v20.x.x

    # Check pnpm
    pnpm --version # Expected: 10.19.0

    # Check git
    git --version # Expected: 2.x.x

    # Check PostgreSQL client
    psql --version # Expected: psql (PostgreSQL) 15.x

    # Check GitHub CLI
    gh --version # Expected: gh version 2.x.x

    # Test database connection
    pnpm psql:status # Expected: Connected to tvl_dev

Optional: Claude Code CLI Setup

What is Claude Code CLI?

Claude Code is an AI-powered development assistant from Anthropic. It's completely optional - the platform works perfectly without it.

When to Install:

  • ✅ You want AI assistance for code generation, debugging, or analysis
  • ✅ You're comfortable with AI-assisted development
  • ✅ You want to leverage Claude's 200K token context window

When to Skip:

  • ❌ You prefer traditional development workflows
  • ❌ Team policy restricts AI tools
  • ❌ You don't have an Anthropic API key or Claude subscription

Installation (Optional):

The Claude Code CLI is pre-installed in the DevContainer via the post-create.sh script. To use it:

  1. Authenticate Claude Code:

    # Inside DevContainer
    claude login

    # Follow prompts:
    # - Choose authentication method (Claude App or API Key)
    # - Sign in with your Anthropic account
  2. Verify Installation:

    claude --version
    # Expected: Claude Code CLI version x.x.x

    claude "What is the purpose of the organizations table?"
    # Expected: Claude analyzes your codebase and responds
  3. Update Permissions (Optional): Edit .claude/settings.local.json to customize what Claude can access:

    {
    "permissions": {
    "allow": [
    "Bash(git:*)",
    "Bash(pnpm:*)",
    "Bash(psql:*)",
    "WebSearch"
    ],
    "deny": [
    "Read(**/.env*)",
    "Edit(**/.env*)"
    ]
    }
    }

Using Claude Code (if installed):

# Inside DevContainer terminal
claude "Help me implement booking cancellation feature"
claude "Review the database schema for RLS policies"
claude "Run tests and fix any failures"

# From outside container (using alias)
# Add to ~/.bashrc or ~/.zshrc:
alias claude-dev='docker compose -f ~/projects/the-villa-life/.devcontainer/docker-compose.yml exec app claude'

# Then use from anywhere:
claude-dev "What's the current status of migrations?"

Note: All project documentation (CLAUDE.md, Cursor rules, ADRs) works whether or not you use Claude Code CLI. It's designed to help human developers too!


Secrets Management with Doppler

⚠️ NEVER commit secrets to version control.

The TVL Platform uses Doppler for centralized secrets management across all environments.

Why Doppler?

FeatureWithout DopplerWith Doppler
Setup Time2+ hours (manual .env files)10 minutes
Secret Rotation2+ hours (update everywhere)10 minutes (auto-sync)
Team Onboarding30+ min (sharing credentials)5 minutes (invite to project)
Security❌ Secrets in Slack/email✅ SOC 2 Type II certified
Audit Trail❌ No visibility✅ Who accessed what, when
EnvironmentsManual managementAutomatic sync

Doppler Setup (Quick Reference)

📖 For detailed setup instructions, see: Doppler Quickstart Guide

Quick Setup:

  1. Install Doppler CLI:

    # macOS
    brew install dopplerhq/cli/doppler

    # Windows (WSL) / Linux
    curl -Ls https://cli.doppler.com/install.sh | sudo sh

    # Verify installation
    doppler --version
  2. Authenticate:

    doppler login
    # Opens browser → Sign in with your Doppler account
  3. Setup Project:

    cd ~/projects/the-villa-life

    # Non-interactive setup (recommended)
    doppler setup --project tvl-mvp-v0 --config dev

    # Verify configuration
    doppler configure get project config --plain
    # Should show: tvl-mvp-v0 and dev
  4. Add Secrets (First-Time Setup):

    # Add all local development secrets
    doppler secrets set \
    DATABASE_ENVIRONMENT="local" \
    DATABASE_URL="postgresql://tvl_user:tvl_password@postgres:5432/tvl_dev" \
    DATABASE_TEST_URL="postgresql://tvl_user:tvl_password@postgres:5432/tvl_test" \
    NODE_ENV="development"

    # Skip if secrets already exist in Doppler
  5. Download Secrets to .env.local:

    # Download secrets to .env.local
    doppler secrets download --no-file --format env > .env.local

    # Verify
    cat .env.local | grep DATABASE_URL
    # Should show: DATABASE_URL=postgresql://tvl_user:tvl_password@postgres:5432/tvl_dev

Doppler Environment Structure

tvl-mvp-v0/
├── dev ← Local development (Docker PostgreSQL)
├── dev_personal ← Personal development configuration
├── stg ← Staging environment (Supabase)
└── prd ← Production environment (Supabase)

Key Secrets Managed by Doppler

Secret NameEnvironmentsUsed For
DATABASE_URLAllPostgreSQL connection string
DATABASE_TEST_URLdevelopmentTest database connection
SUPABASE_URLintegration, staging, productionSupabase project URL
SUPABASE_ANON_KEYintegration, staging, productionClient-side API calls
SUPABASE_SERVICE_ROLE_KEYintegration, staging, productionServer-side admin operations
LINEAR_API_KEYAllLinear integration
HOSTAWAY_CLIENT_IDAllHostaway PMS integration
HOSTAWAY_CLIENT_SECRETAllHostaway authentication
STRIPE_SECRET_KEYAll (V1.0+)Payment processing

Developer Workflows

Daily Development:

# Sync latest secrets (if team updated)
doppler secrets download --no-file --format env > .env.local

# Rebuild DevContainer to load new secrets
# F1 → Dev Containers: Rebuild Container

# Or restart without rebuild:
docker compose -f .devcontainer/docker-compose.yml restart app

Switching Environments:

# Switch to staging (Supabase staging)
doppler setup --project tvl-mvp-v0 --config stg
doppler secrets download --no-file --format env > .env.local

# Switch back to local development
doppler setup --project tvl-mvp-v0 --config dev
doppler secrets download --no-file --format env > .env.local

# Restart container to load new environment
# F1 → Dev Containers: Rebuild Container

Adding New Secrets:

# Add secret via CLI
doppler secrets set NEW_API_KEY=value123 --config dev

# Or use Doppler Dashboard
# https://dashboard.doppler.com/ → tvl-mvp-v0 → dev
# Click "Add Secret"

Rotating Secrets:

# Update secret in Doppler
doppler secrets set STRIPE_SECRET_KEY=sk_live_NEW_KEY --config prd

# Notify team (Slack/Linear)
# "Secrets rotated. Run: doppler secrets download > .env.local && rebuild"

# All developers auto-sync on next rebuild (10 min vs 2 hours manually)

Security Best Practices

  • Always use Doppler for secrets (don't create .env files manually)
  • Add .env.local to .gitignore (already done)
  • Rotate secrets quarterly or when team members leave
  • Use environment-specific configs (don't use production secrets in development)
  • Review Doppler audit logs monthly (Settings → Audit Log)
  • Never share secrets via Slack/email (invite to Doppler project instead)
  • Never commit .env* files to version control

Doppler in CI/CD

GitHub Actions Integration:

# .github/workflows/deploy-staging.yml
name: Deploy to Staging

on:
push:
branches: [main]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install Doppler CLI
uses: dopplerhq/cli-action@v3

- name: Inject Doppler secrets
run: doppler secrets download --no-file --format env > .env.staging
env:
DOPPLER_TOKEN: ${{ secrets.DOPPLER_STAGING_TOKEN }}

- name: Run migrations
run: pnpm db:migrate
env:
DATABASE_URL: ${{ secrets.DOPPLER_DATABASE_URL }}

Setup Doppler Service Tokens:

  1. Go to https://dashboard.doppler.com/ → tvl-mvp-v0 → stg
  2. Settings → Service Tokens → Generate
  3. Copy token
  4. GitHub repo → Settings → Secrets → New repository secret
  5. Name: DOPPLER_STAGING_TOKEN, Value: dp.st.xxx

Database Configurations

Decision Matrix: Which Database Should You Use?

ScenarioDatabaseWhy
Local DevelopmentDocker PostgreSQL✅ Fastest iteration, full control, RLS testing
Integration TestingDocker PostgreSQL OR Remote Staging✅ Isolated tests, consistent CI/CD
Feature Branch TestingRemote Staging✅ Test with production-like data
Staging EnvironmentRemote Supabase✅ Production parity, team collaboration
ProductionRemote Supabase✅ Managed service, scalability, backups

Environment Configurations

When to use:

  • Daily development work
  • Testing database migrations
  • Testing RLS policies
  • Unit and integration tests
  • Need to reset/destroy database frequently

Pros:

  • Fast: Sub-millisecond latency
  • Isolated: Your own database instance
  • Safe: Can reset without affecting others
  • Offline: Works without internet
  • Free: No API limits or costs
  • RLS Testing: Full control for policy testing

Cons:

  • ❌ Doesn't test against production Supabase features
  • ❌ Requires Docker Desktop

Setup:

# 1. Ensure Docker Desktop is running

# 2. Start PostgreSQL in dev container
# Open in VS Code -> "Reopen in Container"
# OR manually:
docker compose -f .devcontainer/docker-compose.yml up -d

# 3. Environment file is already set (.env.local)
# Uses: postgresql://tvl_user:tvl_password@localhost:5432/tvl_dev

# 4. Run migrations
pnpm db:setup
pnpm db:migrate
pnpm db:seed

Configuration (.env.local):

NODE_ENV=development
DATABASE_URL=postgresql://tvl_user:tvl_password@localhost:5432/tvl_dev
DATABASE_TEST_URL=postgresql://tvl_user:tvl_password@localhost:5432/tvl_test

2. Local Development (Remote Supabase)

When to use:

  • Testing Supabase-specific features (Auth, Storage, Realtime)
  • Need to share data with team members
  • Testing production-like scenarios
  • Don't want to run Docker locally

Pros:

  • Production Parity: Exact same as staging/production
  • Supabase Features: Test Auth, Storage, Realtime
  • No Docker: Lighter local setup

Cons:

  • Slower: Network latency (100-500ms vs <1ms)
  • Shared: Can conflict with other developers
  • Rate Limits: Free tier has limits
  • Internet Required: Can't work offline
  • Destructive Testing: Risky to reset database

Setup:

# 1. Create a Supabase project (if not exists)
# Visit: https://app.supabase.com/

# 2. Get connection details
# Project Settings -> Database -> Connection string (URI)

# 3. Create .env.local.remote
cp .env.example .env.local.remote

# 4. Update .env.local.remote with Supabase credentials
DATABASE_URL=postgresql://postgres:[YOUR-PASSWORD]@[PROJECT-REF].supabase.co:5432/postgres
SUPABASE_URL=https://[PROJECT-REF].supabase.co
SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# 5. Use this environment
mv .env.local .env.local.docker # Backup Docker config
mv .env.local.remote .env.local

# 6. Run migrations (CAUTION: affects shared database)
pnpm db:migrate

# Switch back when needed
mv .env.local .env.local.remote
mv .env.local.docker .env.local

Best Practices:

  • ⚠️ Create separate Supabase project for local dev (don't share staging)
  • ⚠️ Never run migrations against shared staging from local
  • ⚠️ Use read-only queries when possible
  • ⚠️ Coordinate with team before destructive operations

3. Staging Environment

When to use:

  • Pre-production testing
  • QA and UAT
  • Integration testing with external APIs
  • Demo environments

Configuration:

# .env.staging (DO NOT COMMIT)
NODE_ENV=staging

# Supabase Staging Project
DATABASE_URL=postgresql://postgres:[PASSWORD]@[STAGING-REF].supabase.co:5432/postgres
SUPABASE_URL=https://[STAGING-REF].supabase.co
SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# Staging API endpoints
API_BASE_URL=https://api-staging.thevillalife.com
NEXT_PUBLIC_APP_URL=https://staging.thevillalife.com

# External integrations (sandbox/test accounts)
HOSTAWAY_CLIENT_ID=staging-client-id
STRIPE_SECRET_KEY=sk_test_...

Deployment:

  • Use GitHub Actions with environment secrets
  • Never commit .env.staging to version control
  • Use environment variables in deployment platform

4. Production Environment

When to use:

  • Live production traffic
  • Real customer data
  • Mission-critical operations

Configuration:

# .env.production (NEVER COMMIT - use secrets manager)
NODE_ENV=production

# Supabase Production Project
DATABASE_URL=postgresql://postgres:[PASSWORD]@[PROD-REF].supabase.co:5432/postgres
SUPABASE_URL=https://[PROD-REF].supabase.co
SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# Production API endpoints
API_BASE_URL=https://api.thevillalife.com
NEXT_PUBLIC_APP_URL=https://app.thevillalife.com

# Production integrations
HOSTAWAY_CLIENT_ID=production-client-id
STRIPE_SECRET_KEY=sk_live_...

# Observability
SENTRY_DSN=https://...@sentry.io/...
SENTRY_ENVIRONMENT=production

Security Requirements:

  • 🔒 Use secrets manager (GitHub Secrets, AWS Secrets Manager, Vercel Env Vars)
  • 🔒 Enable Supabase RLS on all tables
  • 🔒 Rotate credentials regularly
  • 🔒 Enable audit logging
  • 🔒 Use connection pooling (Supabase includes PgBouncer)

Database Migration Strategy

Local Development (Docker)

# Create migration locally
pnpm db:migrate:create add_new_feature

# Test migration (safe - local database)
pnpm db:migrate

# Test rollback
pnpm db:rollback

# Reset and re-run all migrations
pnpm db:reset

Staging/Production (Supabase)

# NEVER run migrations directly from local machine
# Use CI/CD pipeline instead

# GitHub Actions example:
# 1. PR merged to main branch
# 2. CI runs migrations on staging
# 3. Manual approval required
# 4. CI runs migrations on production

Migration Safety Rules:

  1. ✅ Test migrations locally first (Docker PostgreSQL)
  2. ✅ Review migration SQL carefully
  3. ✅ Use transactions (already handled by migrator)
  4. ✅ Test rollback scripts
  5. ✅ Apply to staging before production
  6. ✅ Backup production before migrations
  7. ❌ NEVER run migrations manually on production
  8. ❌ NEVER skip testing locally

Row-Level Security (RLS) Testing

Critical: Always test RLS policies with local Docker PostgreSQL.

Why local testing is required:

  • Supabase RLS can't be easily bypassed for testing
  • Need to simulate different user contexts
  • Destructive tests (creating/deleting orgs) are unsafe on remote

Testing workflow:

# 1. Use local Docker database
# Ensure .env.local points to localhost

# 2. Run RLS tests
pnpm test:rls

# 3. Tests automatically:
# - Create isolated test organizations
# - Set app.current_org_id session variable
# - Verify RLS policies enforce tenant isolation
# - Clean up test data

# Example test:
test('Users can only see their organization', async () => {
const org1 = await createTestOrg('Org 1');
const org2 = await createTestOrg('Org 2');

// Set session to org1
await pool.query(`SET app.current_org_id = '${org1.id}'`);

// Should only see org1 data
const result = await pool.query('SELECT * FROM organizations');
expect(result.rows).toHaveLength(1);
expect(result.rows[0].id).toBe(org1.id);
});

Switching Between Environments

Recommended: Use Doppler for environment switching (see Secrets Management).

# Switch to local development
doppler setup --project tvl-mvp-v0 --config dev
doppler secrets download --no-file --format env > .env.local

# Switch to personal development
doppler setup --project tvl-mvp-v0 --config dev_personal
doppler secrets download --no-file --format env > .env.local

# Switch to staging (for testing only, not regular development)
doppler setup --project tvl-mvp-v0 --config stg
doppler secrets download --no-file --format env > .env.local

# Restart container to load new environment
docker compose -f .devcontainer/docker-compose.yml restart app
# Or in VS Code: F1 → "Dev Containers: Rebuild Container"

Without Doppler (Legacy)

Create scripts/switch-env.sh:

#!/bin/bash
# Switch between environment configurations (legacy method)

ENV=$1

case $ENV in
local)
cp .env.local.docker .env.local
echo "✅ Switched to local Docker PostgreSQL"
;;
remote)
cp .env.local.remote .env.local
echo "✅ Switched to remote Supabase"
;;
staging)
echo "⚠️ Staging environment should only be used in CI/CD"
echo "⚠️ Consider using Doppler instead: doppler setup --project tvl-mvp-v0 --config stg"
;;
*)
echo "Usage: ./scripts/switch-env.sh [local|remote]"
echo ""
echo "💡 Tip: Use Doppler for easier environment switching:"
echo " doppler setup --project tvl-mvp-v0 --config dev"
exit 1
;;
esac

VS Code Tasks

Add to .vscode/tasks.json:

{
"version": "2.0.0",
"tasks": [
{
"label": "Switch to Local DB",
"type": "shell",
"command": "cp .env.local.docker .env.local",
"problemMatcher": []
},
{
"label": "Switch to Remote DB",
"type": "shell",
"command": "cp .env.local.remote .env.local",
"problemMatcher": []
}
]
}

Dev Container Configuration

The dev container supports both local and remote databases:

Local Docker PostgreSQL (Default)

// .devcontainer/devcontainer.json
{
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"containerEnv": {
"DATABASE_URL": "postgresql://tvl_user:tvl_password@postgres:5432/tvl_dev"
}
}

PostgreSQL runs in a sidecar container, accessible at postgres:5432.

Remote Supabase in Dev Container

// .devcontainer/devcontainer.json (override)
{
"containerEnv": {
"DATABASE_URL": "${localEnv:DATABASE_URL}" // Pass from host
}
}

Then set DATABASE_URL on your host machine or in .env.local.

Recommendation: Use local Docker by default, remote only when needed.


Cost Considerations

Local Docker PostgreSQL

  • Cost: Free ✅
  • Performance: Fastest
  • Best for: Daily development

Supabase Free Tier

  • Database: 500 MB
  • Bandwidth: 2 GB
  • API Requests: Unlimited
  • Best for: Small staging/dev projects

Supabase Pro ($25/month per project)

  • Database: 8 GB (+ $0.125/GB)
  • Bandwidth: 50 GB (+ $0.09/GB)
  • API Requests: Unlimited
  • Best for: Staging + Production

Recommended Setup:

  1. Local Dev: Docker (free)
  2. Staging: Supabase Pro
  3. Production: Supabase Pro (separate project)

Total monthly cost: $50/month (Staging + Production)


Troubleshooting

Can't connect to local PostgreSQL

# Check Docker is running
docker ps

# Check PostgreSQL logs
docker logs tvl-postgres

# Verify connection
psql postgresql://tvl_user:tvl_password@localhost:5432/tvl_dev

Can't connect to remote Supabase

# Test connection
psql "postgresql://postgres:[PASSWORD]@[REF].supabase.co:5432/postgres"

# Check network
ping [REF].supabase.co

# Verify credentials in Supabase dashboard
# Settings -> Database -> Connection string

Migrations fail on Supabase

# Common issues:
# 1. RLS is enabled - need to use service role key
# 2. Connection pooling - use port 5432 (direct), not 6543 (pooler)
# 3. SSL required - add ?sslmode=require to connection string

# Correct format:
DATABASE_URL=postgresql://postgres:[PASSWORD]@[REF].supabase.co:5432/postgres?sslmode=require

Dev container using wrong database

# Check environment variables
echo $DATABASE_URL

# Override in dev container
# Edit .devcontainer/devcontainer.json -> containerEnv

Best Practices Summary

✅ DO

  1. Use local Docker for daily development

    • Fastest iteration
    • Safe to break
    • RLS testing
  2. Test migrations locally first

    • Always test with Docker
    • Test rollbacks
    • Verify RLS policies
  3. Use Supabase for staging/production

    • Managed service
    • Scalability
    • Built-in backups
  4. Separate Supabase projects

    • Local dev (optional)
    • Staging
    • Production
  5. Use environment-specific configs

    • .env.local (Docker)
    • .env.staging (not committed)
    • .env.production (secrets manager)

❌ DON'T

  1. Don't run migrations manually on production

    • Use CI/CD only
    • Require approvals
    • Always backup first
  2. Don't share staging database for local dev

    • Use Docker instead
    • Avoid conflicts
    • Faster development
  3. Don't commit credentials

    • Use .env.*.local for Docker
    • Use secrets manager for remote
    • Add .env.staging and .env.production to .gitignore
  4. Don't test destructive operations on remote

    • Use local Docker
    • Create separate test project if needed
    • Coordinate with team

Quick Reference

TaskEnvironmentCommand
Daily developmentLocal Dockerdocker compose up -d + .env.local
Test migrationsLocal Dockerpnpm db:migrate
Test RLS policiesLocal Dockerpnpm test:rls
Feature branch testingStaging SupabaseDeploy to staging via CI/CD
Production deploymentProduction SupabaseDeploy via CI/CD


Performance Optimization

Windows + WSL Performance Checklist

If you're experiencing slow performance, verify these settings:

1. Repository Location:

# Check current location
pwd

# ✅ CORRECT: WSL filesystem
/home/<user>/projects/the-villa-life

# ❌ WRONG: Windows filesystem (10-20x slower)
/mnt/c/GitHub/the-villa-life

2. Docker WSL Integration:

# Verify Docker is accessible from WSL
docker ps

# If fails: Docker Desktop → Settings → Resources → WSL Integration
# Enable Ubuntu → Apply & Restart

3. pnpm Cache Location:

# Inside DevContainer
pnpm store path

# ✅ CORRECT: Container filesystem
/home/vscode/.local/share/pnpm/store

# ❌ WRONG: Mounted from Windows
/mnt/c/Users/...

4. DevContainer Volume Mounts:

# Check container mounts
docker inspect the-villa-life-app-1 | grep -A 5 "Mounts"

# Source should be WSL path, not /mnt/c/
# ✅ CORRECT: "Source": "/home/<user>/projects/the-villa-life"
# ❌ WRONG: "Source": "/mnt/c/GitHub/the-villa-life"

Performance Benchmarks

Run these tests to measure your environment performance:

# Inside DevContainer terminal

# Test 1: pnpm install speed
rm -rf node_modules .pnpm-store
time pnpm install --frozen-lockfile
# Target: < 60 seconds

# Test 2: Git operations
time git status
# Target: < 0.2 seconds

# Test 3: TypeScript compilation
time pnpm exec tsc --noEmit
# Target: < 5 seconds

# Test 4: Hot reload (in separate terminal)
pnpm dev
# Edit a file, save, measure reload time
# Target: < 1 second

Expected Results (WSL FS + DevContainer):

OperationTarget TimeSlow (needs optimization)
pnpm install< 60 sec> 2 min
git status< 0.2 sec> 1 sec
tsc --noEmit< 5 sec> 15 sec
Hot reload< 1 sec> 3 sec

Troubleshooting Slow Performance

Issue: pnpm install still slow (> 2 minutes)

# Diagnosis
pwd # Verify you're in WSL filesystem
pnpm store path # Verify cache location

# Solution 1: Move repository to WSL
cd ~
mkdir -p projects
cp -r /mnt/c/GitHub/the-villa-life ~/projects/
cd ~/projects/the-villa-life

# Solution 2: Clear pnpm cache
pnpm store prune
pnpm install --frozen-lockfile

# Solution 3: Rebuild DevContainer
# F1 → "Dev Containers: Rebuild Container"

Issue: Git operations slow (> 1 second)

# Diagnosis
mount | grep workspace
# Should NOT show /mnt/c/ in source

# Solution: Repository is on Windows filesystem
# Move to WSL (see Solution 1 above)

Issue: Hot reload not working or very slow

# Diagnosis
# Check if file watcher is working
pnpm dev
# Edit a file - watch terminal for reload message

# Solution 1: Increase file watcher limit (Linux/WSL)
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

# Solution 2: Check Next.js dev server logs
# Look for "compiling" messages
# Slow compilation indicates repository on Windows FS

# Solution 3: Ensure DevContainer has enough resources
# Docker Desktop → Settings → Resources
# Memory: 8GB+ recommended
# CPUs: 4+ recommended

WSL Configuration Optimization

Create or edit ~/.wslconfig (Windows home directory):

[wsl2]
# Memory allocation (adjust based on your RAM)
memory=8GB

# CPU cores (adjust based on your CPU)
processors=4

# Swap file
swap=2GB

# Localhost forwarding (required for DevContainer)
localhostForwarding=true

# Nested virtualization (for Docker)
nestedVirtualization=true

# Kernel command line
kernelCommandLine=vsyscall=emulate

# Page reporting (improves memory management)
pageReporting=true

# GUI applications (optional)
guiApplications=false

Apply changes:

# In PowerShell (as Administrator)
wsl --shutdown

# Wait 10 seconds, then restart WSL
wsl