docs: update architecture and development docs to cover client workspace
- add client workspace section to architecture diagram and description - split development.md commands into server and client per-workspace - document client tech stack, directory layout, routing, and theming - add Client overview section with Storybook test instructions
This commit is contained in:
+17
-1
@@ -1,11 +1,19 @@
|
|||||||
# Architecture
|
# Architecture
|
||||||
|
|
||||||
```
|
```
|
||||||
|
┌─────────────────────────────────────────┐
|
||||||
|
│ Browser (React SPA — client/) │
|
||||||
|
│ │
|
||||||
|
│ EnvironmentsPage KeysPage │
|
||||||
|
│ SessionsPage ScenariosPage │
|
||||||
|
└───────────────────┬─────────────────────┘
|
||||||
|
│ HTTP REST (:13000)
|
||||||
|
│
|
||||||
MCP client (AI agent / VS Code Copilot)
|
MCP client (AI agent / VS Code Copilot)
|
||||||
│ HTTP /mcp (Streamable MCP)
|
│ HTTP /mcp (Streamable MCP)
|
||||||
▼
|
▼
|
||||||
┌──────────────────────────────────────┐
|
┌──────────────────────────────────────┐
|
||||||
│ NestJS app (src/) │
|
│ NestJS app (server/src/) │
|
||||||
│ │
|
│ │
|
||||||
│ McpService ← all MCP tools │
|
│ 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.
|
- **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.
|
- **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)).
|
- **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.
|
||||||
|
|||||||
+127
-22
@@ -5,16 +5,23 @@
|
|||||||
- Node.js 20+
|
- Node.js 20+
|
||||||
- Docker + Docker Compose
|
- 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
|
```bash
|
||||||
npm install
|
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.
|
Copy `.env.example` to `.env` and fill in the required values before running.
|
||||||
|
|
||||||
### Environment variables
|
### Environment variables (server)
|
||||||
|
|
||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@@ -27,74 +34,122 @@ Copy `.env.example` to `.env` and fill in the required values before running.
|
|||||||
|
|
||||||
## Starting the application
|
## Starting the application
|
||||||
|
|
||||||
|
### Server
|
||||||
|
|
||||||
**Development** (watch mode, restarts on file changes):
|
**Development** (watch mode, restarts on file changes):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run start:dev
|
npm -w server run start:dev
|
||||||
```
|
```
|
||||||
|
|
||||||
**Production build, then start**:
|
**Production build, then start**:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm -w server run build
|
||||||
npm run start:prod
|
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
|
## Running tests
|
||||||
|
|
||||||
|
### Server (Jest)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run test
|
npm -w server run test
|
||||||
```
|
```
|
||||||
|
|
||||||
Run a single spec file:
|
Run a single spec file:
|
||||||
|
|
||||||
```bash
|
```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:
|
Watch mode:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run test:watch
|
npm -w server run test:watch
|
||||||
```
|
```
|
||||||
|
|
||||||
Enable verbose NestJS log output during tests:
|
Enable verbose NestJS log output during tests:
|
||||||
|
|
||||||
```bash
|
```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
|
## 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
|
```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
|
## 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
|
```bash
|
||||||
# report issues
|
npm -w server run lint # report issues
|
||||||
npm run lint
|
npm -w server run lint:fix # report and auto-fix
|
||||||
|
|
||||||
# report and auto-fix where possible
|
|
||||||
npm run lint: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
|
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.
|
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
|
```bash
|
||||||
docker compose logs -f
|
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 `<html>` before React mounts (anti-FOUC inline script in `index.html`).
|
||||||
|
|||||||
Reference in New Issue
Block a user