# Development ## Prerequisites - Node.js 20+ - Docker + Docker Compose The repository is a **npm workspace monorepo** with two packages: | Workspace | Directory | Description | |---|---|---| | `server` | `server/` | NestJS API + MCP server | | `client` | `client/` | React 19 + Vite admin UI | Install all dependencies from the repo root: ```bash npm install npx playwright install chromium # first time only (server) ``` Copy `.env.example` to `.env` and fill in the required values before running. ### Environment variables (server) | Variable | Default | Description | |---|---|---| | `PORT` | `3000` | HTTP port | | `KEYS_DIR` | `keys` | Directory for key material used by credential/snippet workflows | | `DB_PATH` | `data/sessions.db` | SQLite database file | | `SESSION_IDLE_TIMEOUT_MINUTES` | `30` | Idle timeout before open sessions are closed | | `SESSION_DELETE_CLOSED_DAYS` | `7` | Retention period for closed sessions | | `PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH` | _(Playwright default)_ | Path to Chromium binary. Set automatically in Docker (`/usr/bin/chromium`). | --- ## Starting the application ### Server **Development** (watch mode, restarts on file changes): ```bash npm -w server run start:dev ``` **Production build, then start**: ```bash npm -w server run build npm -w server run start:prod ``` The server listens on port **3000** by default. ### Client **Development** (Vite dev server with HMR): ```bash npm -w client run dev ``` The Vite dev server runs on **http://localhost:5173** and proxies these API prefixes to `localhost:13000` (or `localhost:3000` when running server locally): - `/environments` - `/credentials` - `/snippets` - `/sessions` - `/scenarios` **Production build**: ```bash npm -w client run build ``` The built files are emitted to `client/dist/`. --- ## Running tests ### Server (Jest) ```bash npm -w server run test ``` Run a single spec file: ```bash npm -w server run test -- --no-coverage test/scenario.controller.spec.ts ``` Watch mode: ```bash npm -w server run test:watch ``` Enable verbose NestJS log output during tests: ```bash npm -w server run test:debug ``` ### Client (Vitest + Storybook) Storybook interaction tests (runs all `*.stories.tsx` files): ```bash npm -w client run test:storybook ``` Launch Storybook dev server (with live preview): ```bash npm -w client run storybook ``` --- ## Formatting code Both workspaces use [Prettier](https://prettier.io/). **Server** — rewrites `src/**/*.ts` and `test/**/*.ts`: ```bash npm -w server run format ``` **Client** — rewrites `src/**/*.{ts,tsx}` and `.storybook/**/*.{ts,tsx}`: ```bash npm -w client run format ``` --- ## Linting Both workspaces use [ESLint](https://eslint.org/) with `typescript-eslint`. The client also includes `eslint-plugin-react-hooks` and `eslint-plugin-react-refresh`. **Server:** ```bash npm -w server run lint # report issues npm -w server run lint:fix # report and auto-fix ``` **Client:** ```bash npm -w client run lint # report issues npm -w client run lint:fix # report and auto-fix ``` Both workspaces target zero errors. Run lint before committing. --- ## Building the container ```bash docker compose build ``` To rebuild without the layer cache: ```bash docker compose build --no-cache ``` --- ## Running with Docker Compose Start (detached): ```bash docker compose up -d ``` Build and start in one step: ```bash docker compose up -d --build ``` The server API is exposed at **http://localhost:13000**. SQLite data is persisted in `./data/` and key files are mounted from `./keys/` — both directories are volume-mounted into the container. Stop and remove containers: ```bash docker compose down ``` View logs: ```bash docker compose logs -f ``` --- ## Client overview The client (`client/`) is a React 19 + TypeScript SPA built with Vite. It provides a browser UI for managing environments, credentials, snippets, sessions, scenarios, and runs. ### Tech stack | Library | Purpose | |---|---| | React 19 + TypeScript | UI framework | | Vite 6 | Dev server and bundler | | react-router-dom (HashRouter) | Client-side routing | | i18next + react-i18next | Internationalisation | | lucide-react | Icon library | | moment | Relative timestamp formatting | | ESLint 10 + Prettier | Linting and formatting | | Storybook 10 + Vitest | Component development and testing | ### Directory layout ``` client/ src/ api/ API client modules (environments, credentials, snippets, sessions, scenarios) hooks/ useTheme (light/dark persistence) i18n/ i18next bootstrap + locales/en.json pages/ Environment/Credential/Snippet/Session/Scenario/Run pages ui/ Reusable component library Badge, Breadcrumbs, Button, Card, Input, Select, SidePanel, Table, ThemeSwitcher, Timestamp .storybook/ stories/ *.stories.tsx for all ui/ components ``` ### Routing Hash-based routing (`/#/path`) avoids conflicts with the Vite dev-server proxy. Default route redirects to `/#/scenarios`. | Route | Page | |---|---| | `/#/environments` | Environment list | | `/#/credentials` | Credential list | | `/#/snippets` | Snippet list | | `/#/sessions` | Session list | | `/#/scenarios` | Scenario list | | `/#/runs` | Cross-scenario runs list | ### Theming Light/dark theme is toggled by the `ThemeSwitcher` button in the sidebar footer. The selection is persisted to `localStorage` and applied as `data-theme` on `` before React mounts (anti-FOUC inline script in `index.html`). The sidebar footer also shows the app version read from the workspace root `package.json` and injected via Vite `define`.