diff --git a/docs/architecture.md b/docs/architecture.md index 759781c..278a98b 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,11 +1,19 @@ # Architecture ``` +┌─────────────────────────────────────────┐ +│ Browser (React SPA — client/) │ +│ │ +│ EnvironmentsPage KeysPage │ +│ SessionsPage ScenariosPage │ +└───────────────────┬─────────────────────┘ + │ HTTP REST (:13000) + │ MCP client (AI agent / VS Code Copilot) │ HTTP /mcp (Streamable MCP) ▼ ┌──────────────────────────────────────┐ -│ NestJS app (src/) │ +│ NestJS app (server/src/) │ │ │ │ McpService ← all MCP tools │ │ │ @@ -32,3 +40,11 @@ MCP client (AI agent / VS Code Copilot) - **CodeExecutorService** — compiles and runs user-supplied Playwright JS inside a sandboxed `async` function with `page`, `context`, and `helpers` in scope. - **ScenarioService** — CRUD for scenarios, steps, runs, and run logs; import/export. - **ScenarioSchedulerService** — polls for pending step runs every second and executes them. All steps in the same run share **one browser instance** (see [scenario.md](scenario.md)). + +## Client (`client/`) + +A React 19 + TypeScript SPA served separately by Vite during development. In Docker Compose the same build artefacts are served statically alongside the API. + +The client calls the server REST endpoints directly — there is no separate BFF layer. Routing uses HashRouter so the Vite proxy and server-side routes are never ambiguous. + +See [development.md](development.md) for the full client tech stack and directory layout. diff --git a/docs/development.md b/docs/development.md index 868a1eb..cf3dba0 100644 --- a/docs/development.md +++ b/docs/development.md @@ -5,16 +5,23 @@ - Node.js 20+ - Docker + Docker Compose -Install dependencies: +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 +npx playwright install chromium # first time only (server) ``` Copy `.env.example` to `.env` and fill in the required values before running. -### Environment variables +### Environment variables (server) | Variable | Default | Description | |---|---|---| @@ -27,74 +34,122 @@ Copy `.env.example` to `.env` and fill in the required values before running. ## Starting the application +### Server + **Development** (watch mode, restarts on file changes): ```bash -npm run start:dev +npm -w server run start:dev ``` **Production build, then start**: ```bash -npm run build -npm run start:prod +npm -w server run build +npm -w server run start:prod ``` -The application listens on port **3000** by default. +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 all API paths (`/environments`, `/sessions`, `/scenarios`, `/keys`, `/login`, `/mcp`) to the server at `localhost:3000`. + +**Production build**: + +```bash +npm -w client run build +``` + +The built files are emitted to `client/dist/`. --- ## Running tests +### Server (Jest) + ```bash -npm run test +npm -w server run test ``` Run a single spec file: ```bash -npm run test -- --no-coverage test/scenario.controller.spec.ts +npm -w server run test -- --no-coverage test/scenario.controller.spec.ts ``` Watch mode: ```bash -npm run test:watch +npm -w server run test:watch ``` Enable verbose NestJS log output during tests: ```bash -npm run test:debug +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 -[Prettier](https://prettier.io/) is used to format all TypeScript source and test files: +Both workspaces use [Prettier](https://prettier.io/). + +**Server** — rewrites `src/**/*.ts` and `test/**/*.ts`: ```bash -npm run format +npm -w server run format ``` -This rewrites `src/**/*.ts` and `test/**/*.ts` in place. +**Client** — rewrites `src/**/*.{ts,tsx}` and `.storybook/**/*.{ts,tsx}`: + +```bash +npm -w client run format +``` --- ## Linting -[ESLint](https://eslint.org/) with `typescript-eslint` and `eslint-config-prettier` is used: +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 -# report issues -npm run lint - -# report and auto-fix where possible -npm run lint:fix +npm -w server run lint # report issues +npm -w server run lint:fix # report and auto-fix ``` -The project targets zero errors. Run lint before committing. +**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. --- @@ -126,7 +181,7 @@ Build and start in one step: docker compose up -d --build ``` -The application is exposed at **http://localhost:13000**. +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. @@ -141,3 +196,53 @@ 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, sessions, keys, and scenarios. + +### 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, keys, sessions, scenarios) + hooks/ useTheme (light/dark persistence) + i18n/ i18next bootstrap + locales/en.json + pages/ EnvironmentsPage, KeysPage, SessionsPage, ScenariosPage + 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 | +| `/#/keys` | Key list | +| `/#/sessions` | Session list | +| `/#/scenarios` | Scenario list | + +### Theming + +Light/dark theme is toggled by the `ThemeSwitcher` button in the sidebar header. The selection is persisted to `localStorage` and applied as `data-theme` on `` before React mounts (anti-FOUC inline script in `index.html`).