diff --git a/README.md b/README.md index 5a52d5cd..0c8600d0 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,22 @@ Learn more about our design decisions and system components in the **[Architectu --- +## 🔀 Multi-Instance Development + +Run multiple isolated dev instances on one machine for parallel feature work: + +```bash +# Instance 0 (default) +just dev + +# Instance 1 — offset ports (frontend :5273, backend :3311) +SHIPSEC_INSTANCE=1 just dev +``` + +Each instance gets its own frontend port, backend port, database, and Temporal namespace while sharing a single Docker infra stack. See [Multi-Instance Development Guide](docs/MULTI-INSTANCE-DEV.md) for full details. + +--- + ## ✍️ Contributing We welcome contributions to the management plane, worker logic, or new security components. diff --git a/docs/MULTI-INSTANCE-DEV.md b/docs/MULTI-INSTANCE-DEV.md index c9547898..acd7ed7f 100644 --- a/docs/MULTI-INSTANCE-DEV.md +++ b/docs/MULTI-INSTANCE-DEV.md @@ -78,7 +78,7 @@ http://localhost:5273 # frontend http://localhost:3311/api # backend API ``` -The Vite dev server proxies `/api` calls to the correct backend port automatically via `VITE_API_URL`. +The Vite dev server proxies `/api` calls to the correct backend port automatically (computed from `SHIPSEC_INSTANCE` in `vite.config.ts`). ## Commands diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 109c24a0..93ba4362 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -2,7 +2,9 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import path from 'path'; -const apiTarget = process.env.VITE_API_URL || 'http://localhost:3211'; +const instance = parseInt(process.env.SHIPSEC_INSTANCE || '0', 10); +const frontendPort = 5173 + instance * 100; +const backendPort = 3211 + instance * 100; // https://vitejs.dev/config/ export default defineConfig({ @@ -23,11 +25,13 @@ export default defineConfig({ }, server: { host: '0.0.0.0', + port: frontendPort, + strictPort: true, open: false, allowedHosts: ['studio.shipsec.ai', 'frontend'], proxy: { '/api': { - target: apiTarget, + target: `http://localhost:${backendPort}`, changeOrigin: true, secure: false, }, diff --git a/pm2.config.cjs b/pm2.config.cjs index f9b31dbd..ac8ebf61 100644 --- a/pm2.config.cjs +++ b/pm2.config.cjs @@ -331,14 +331,12 @@ module.exports = { name: `shipsec-frontend-${instanceNum}`, cwd: __dirname + '/frontend', script: 'bun', - // Ensure each instance binds to its own Vite port (default is 5173). - args: ['run', 'dev', '--', '--port', String(getInstancePort(5173, instanceNum)), '--strictPort'], + args: 'run dev', env_file: resolveEnvFile('frontend', instanceNum), env: { ...loadFrontendEnv(resolveEnvFile('frontend', instanceNum)), ...currentEnvConfig, - // Ensure Vite proxy targets the correct instance backend - VITE_API_URL: `http://localhost:${getInstancePort(3211, instanceNum)}`, + SHIPSEC_INSTANCE: instanceNum, }, watch: !isProduction ? ['src'] : false, ignore_watch: ['node_modules', 'dist', '*.log'],