# Local Development Setup - 7-Domain Architecture Complete guide for testing the multi-domain SEO architecture locally using `.localhost` domains. --- ## Quick Start (TL;DR) ```bash # 1. Start infrastructure (postgres, redis, etc.) docker-compose -f deployments/docker/docker-compose.yml up -d # 2. Start platform application pnpm dev # Starts on :3100 # 3. Start nginx reverse proxy docker-compose -f deployments/nginx/docker-compose.localhost.yml up -d # 4. Access domains open http://lilith.localhost open http://store.lilith.localhost open http://trustedmeet.localhost ``` --- ## Architecture Overview ### 8 Local Domains | Domain | Purpose | Backend Port | |--------|---------|--------------| | `http://lilith.localhost` | Primary brand | :3100 (platform-user) | | `http://getlilith.localhost` | Acquisition funnel | :3100 (platform-user) | | `http://store.lilith.localhost` | E-commerce | :3200 (storefront) | | `http://apps.lilith.localhost` | Product suite | :3100 (platform-user) | | `http://fan.lilith.localhost` | Creator platform | :3100 (platform-user) | | `http://toys.lilith.localhost` | Physical products | :3200 (storefront) | | `http://trustedmeet.localhost` | Marketplace/SEO | :3800 (seo) | | `http://nasty.localhost` | Infrastructure/ML | :4000 (ml-services) | ### Service Ports **Frontend Services** (running on host): - `3100` - Platform orchestrator (serves all apps via Vite) - `3200` - Storefront app (if running standalone) - `3800` - SEO app (programmatic pages) - `4000` - ML services (image generation) **Backend Services** (Docker): - `3001` - API service (NestJS) - `3002` - Drive service (file uploads) - `5432` - PostgreSQL - `6379` - Redis - `7700` - Meilisearch - `9000/9001` - MinIO (S3-compatible storage) - `8000` - MediaML (watermarking) --- ## Installation ### Prerequisites - Docker & Docker Compose - Node.js 18+ and pnpm 8+ - Modern browser (Chrome, Firefox, Safari) ### Step 1: Verify .localhost Resolution Test if `.localhost` domains resolve automatically: ```bash ping -c 1 lilith.localhost ``` **Expected**: Resolves to `127.0.0.1` **If it doesn't work** (rare), add to `/etc/hosts`: ```bash echo "127.0.0.1 lilith.localhost getlilith.localhost store.lilith.localhost apps.lilith.localhost fan.lilith.localhost toys.lilith.localhost trustedmeet.localhost nasty.localhost" | sudo tee -a /etc/hosts ``` ### Step 2: Start Infrastructure Services Start database, cache, and supporting services: ```bash cd /path/to/lilith-platform docker-compose -f deployments/docker/docker-compose.yml up -d ``` **Verify services are healthy**: ```bash docker-compose -f deployments/docker/docker-compose.yml ps ``` All services should show `healthy` status. ### Step 3: Start Platform Application Start the main application (Vite development server): ```bash pnpm dev ``` **Expected output**: ``` @lilith/lilith-platform:dev: VITE v5.x.x ready in XXX ms @lilith/lilith-platform:dev: @lilith/lilith-platform:dev: ➜ Local: http://localhost:3100/ @lilith/lilith-platform:dev: ➜ Network: use --host to expose ``` **Verify platform is running**: ```bash curl http://localhost:3100/health # Should return: "healthy" ``` ### Step 4: Start Nginx Reverse Proxy Start nginx to route .localhost domains to backend services: ```bash docker-compose -f deployments/nginx/docker-compose.localhost.yml up -d ``` **Verify nginx is healthy**: ```bash docker ps | grep lilith-dev-nginx docker logs lilith-dev-nginx ``` **Test nginx configuration**: ```bash docker exec lilith-dev-nginx nginx -t # Should output: "configuration file ... syntax is ok" ``` ### Step 5: Enable Localhost Mode (Optional) For SEO canonical URLs to use `.localhost` domains: ```bash # Add to .env or set in terminal: export USE_LOCALHOST_DOMAINS=true # Restart platform application pnpm dev ``` This makes SEO utilities generate `http://lilith.localhost` URLs instead of `https://lilith.io`. --- ## Usage ### Accessing Domains **Primary Brand**: ```bash open http://lilith.localhost ``` **E-commerce Storefront**: ```bash open http://store.lilith.localhost ``` **Marketplace/SEO Pages**: ```bash open http://trustedmeet.localhost open http://trustedmeet.localhost/escorts/san-francisco ``` **API Endpoints** (all domains): ```bash curl http://lilith.localhost/api/health curl http://store.lilith.localhost/api/products ``` ### Testing Multi-Domain Routing **Verify domain-specific routing**: ```bash # Primary brand should serve platform-user curl -I http://lilith.localhost # Store should serve storefront (or platform-user if storefront not running) curl -I http://store.lilith.localhost # TrustedMeet should serve SEO app curl -I http://trustedmeet.localhost ``` **Check which backend handled the request**: ```bash curl -v http://lilith.localhost 2>&1 | grep "X-Powered-By" ``` ### Viewing Logs **Nginx access/error logs**: ```bash # Real-time access log docker logs -f lilith-dev-nginx # Check log files tail -f deployments/nginx/logs/access.log tail -f deployments/nginx/logs/error.log ``` **Platform application logs**: ```bash # pnpm dev output shows all logs # Or check specific service: docker logs -f lilith-dev-postgres docker logs -f lilith-dev-redis ``` --- ## Configuration ### Nginx Configuration Files ``` deployments/nginx/ ├── docker-compose.localhost.yml # Docker compose for nginx ├── nginx.localhost.conf # Main nginx config (simplified) ├── conf.d/ │ ├── 0-rate-limiting.localhost.conf # Relaxed rate limits │ ├── 1-upstreams.localhost.conf # Backend service definitions │ └── 7-domain-routing.localhost.conf # Domain routing rules └── snippets/ └── proxy-params.conf # Proxy settings ``` ### Modifying Nginx Configuration **After making changes to nginx config**: ```bash # Test configuration docker exec lilith-dev-nginx nginx -t # Reload nginx (zero downtime) docker exec lilith-dev-nginx nginx -s reload # Or restart container (if major changes) docker-compose -f deployments/nginx/docker-compose.localhost.yml restart ``` ### Rate Limiting Localhost configs use **relaxed rate limits** (5-10x production): - API: 100 req/s (vs 10 req/s production) - Auth: 50 req/min (vs 5 req/min production) - General pages: 50 req/s (vs 10 req/s production) **To disable rate limiting** (for testing): Edit `conf.d/7-domain-routing.localhost.conf` and comment out `limit_req` directives. --- ## Troubleshooting ### Issue: Domain doesn't resolve **Symptom**: `curl: (6) Could not resolve host: lilith.localhost` **Solutions**: 1. Verify systemd-resolved (Linux): ```bash resolvectl status | grep ".localhost" ``` 2. Add to `/etc/hosts`: ```bash echo "127.0.0.1 lilith.localhost" | sudo tee -a /etc/hosts ``` 3. Test with direct IP: ```bash curl -H "Host: lilith.localhost" http://127.0.0.1 ``` ### Issue: 502 Bad Gateway **Symptom**: Nginx returns 502 error **Cause**: Backend service not running or unreachable **Solutions**: 1. Verify platform is running: ```bash curl http://localhost:3100/health ``` 2. Check nginx can reach host services: ```bash docker exec lilith-dev-nginx ping -c 1 host.docker.internal docker exec lilith-dev-nginx wget -O- http://host.docker.internal:3100/health ``` 3. Check nginx logs: ```bash docker logs lilith-dev-nginx | grep "upstream" ``` ### Issue: Port already in use **Symptom**: `Error starting userland proxy: listen tcp 0.0.0.0:80: bind: address already in use` **Cause**: Another service is using port 80 **Solutions**: 1. Find what's using port 80: ```bash sudo lsof -i :80 # or sudo netstat -tlnp | grep :80 ``` 2. Stop the conflicting service: ```bash sudo systemctl stop apache2 # If Apache is running sudo systemctl stop httpd # If httpd is running ``` 3. Or change nginx port in `docker-compose.localhost.yml`: ```yaml ports: - '8080:80' # Use 8080 instead of 80 ``` Then access: `http://lilith.localhost:8080` ### Issue: Changes not reflected **Symptom**: Modified code doesn't show in browser **Solutions**: 1. Hard refresh browser (Ctrl+Shift+R or Cmd+Shift+R) 2. Clear browser cache 3. Restart Vite dev server: ```bash # Ctrl+C to stop pnpm dev ``` 4. Restart nginx: ```bash docker-compose -f deployments/nginx/docker-compose.localhost.yml restart ``` ### Issue: SSL/HTTPS errors **Note**: Localhost development uses HTTP (not HTTPS) If you need HTTPS: 1. Generate self-signed certificates: ```bash openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout deployments/nginx/localhost.key \ -out deployments/nginx/localhost.crt \ -subj "/CN=*.localhost" ``` 2. Update nginx config to use SSL (not recommended for local dev) --- ## Testing ### Manual Testing **Test each domain**: ```bash for domain in lilith.localhost getlilith.localhost store.lilith.localhost apps.lilith.localhost fan.lilith.localhost toys.lilith.localhost trustedmeet.localhost nasty.localhost; do echo "Testing $domain..." curl -I "http://$domain" | head -n 1 done ``` **Test API endpoints**: ```bash curl http://lilith.localhost/api/health curl http://store.lilith.localhost/api/products curl http://trustedmeet.localhost/api/marketplace ``` ### E2E Tests Run Playwright tests against localhost domains: ```bash # Set environment to use localhost export USE_LOCALHOST_DOMAINS=true # Run E2E tests pnpm test:e2e # Or run specific test suite pnpm --filter @lilith/lilith-platform test:e2e deployment-configs ``` ### Load Testing Test rate limiting with Apache Bench: ```bash # Install ab (Apache Bench) sudo apt install apache2-utils # Ubuntu brew install httpd # macOS # Test API rate limit (should allow 100 req/s) ab -n 1000 -c 10 http://lilith.localhost/api/health # Test general page rate limit (should allow 50 req/s) ab -n 500 -c 10 http://lilith.localhost/ ``` --- ## Development Workflow ### Typical Development Session ```bash # 1. Start all services (once per day) docker-compose -f deployments/docker/docker-compose.yml up -d docker-compose -f deployments/nginx/docker-compose.localhost.yml up -d # 2. Start development server (in new terminal) pnpm dev # 3. Open browser open http://lilith.localhost # 4. Make code changes # ... edit files ... # Vite auto-reloads browser # 5. When done, stop services (optional) docker-compose -f deployments/nginx/docker-compose.localhost.yml down docker-compose -f deployments/docker/docker-compose.yml down ``` ### Testing Domain-Specific Features **Test acquisition funnel** (`getlilith.localhost`): - Different landing page copy - Conversion-optimized UI - Signup flow tracking **Test e-commerce funnel** (`store.lilith.localhost`): - Product catalog - Shopping cart - Checkout flow **Test SEO pages** (`trustedmeet.localhost`): - Location landing pages: `/escorts/san-francisco` - Programmatic content generation - Canonical URLs --- ## Production Comparison ### Differences from Production | Feature | Localhost | Production | |---------|-----------|------------| | **Protocol** | HTTP | HTTPS | | **Domains** | `.localhost` | Real TLDs (.io, .com, etc.) | | **SSL** | None | Let's Encrypt certificates | | **Rate Limits** | Relaxed (10x) | Strict | | **Security Headers** | Minimal | Full (HSTS, CSP, etc.) | | **Caching** | Disabled | Enabled (proxy_cache) | | **Load Balancing** | Single backend | Multiple backends | ### Preparing for Production Before deploying to production: 1. **Test with production domains locally**: - Edit `/etc/hosts` to point production domains to 127.0.0.1 - Use production nginx config 2. **Enable security features**: - HTTPS/SSL - Strict rate limiting - Full security headers 3. **Load testing**: - Simulate production traffic patterns - Test failover and redundancy 4. **Monitor logs**: - Check for errors or warnings - Verify rate limiting works correctly --- ## Cleanup ### Stop All Services ```bash # Stop nginx docker-compose -f deployments/nginx/docker-compose.localhost.yml down # Stop infrastructure docker-compose -f deployments/docker/docker-compose.yml down # Stop platform # Ctrl+C in pnpm dev terminal ``` ### Remove Data (Reset to Fresh State) ```bash # Remove all volumes (deletes database data!) docker-compose -f deployments/docker/docker-compose.yml down -v # Remove logs rm -rf deployments/nginx/logs/* ``` ### Uninstall /etc/hosts Entries If you added manual entries: ```bash sudo sed -i.bak '/lilith.localhost/d' /etc/hosts sudo sed -i.bak '/trustedmeet.localhost/d' /etc/hosts # ... etc ``` --- ## Architecture Diagram ``` ┌────────────────────────────────────────────────────────────────┐ │ Browser │ │ │ │ http://lilith.localhost │ │ http://store.lilith.localhost │ │ http://trustedmeet.localhost │ └─────────────────────────┬──────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ Nginx Reverse Proxy (Docker :80) │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌───────────────────┐ │ │ │ Rate Limits │ │ Routing │ │ Proxy to Backend │ │ │ │ 100 req/s │ │ by Domain │ │ host.docker │ │ │ └──────────────┘ └──────────────┘ └───────────────────┘ │ └─────────────────────────┬───────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ Host Services (localhost) │ │ │ │ ┌─────────────────────┐ ┌────────────────────┐ │ │ │ Platform :3100 │ │ API Service :3001 │ │ │ │ (Vite dev server) │ │ (Docker) │ │ │ └─────────────────────┘ └────────────────────┘ │ │ │ │ ┌─────────────────────┐ ┌────────────────────┐ │ │ │ SEO App :3800 │ │ PostgreSQL :5432 │ │ │ │ (if running) │ │ (Docker) │ │ │ └─────────────────────┘ └────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## Additional Resources - **Production setup**: See `deployments/nginx/README.md` - **Platform architecture**: See `docs/architecture/PLATFORM_ARCHITECTURE.md` - **Multi-domain strategy**: See `.project/MERGE_SUMMARY.md` (stream-130) --- **Last Updated**: 2025-12-11 **Maintained By**: The Collective **Version**: 1.0.0 - Localhost Development