Skip to content

Commit d418003

Browse files
yasithdevclaude
andcommitted
docs: rewrite widget CLAUDE.md/README against current code (sdk contracts, Wave-14 status, port 9001); AGENTS.md/.agents symlinks
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent c87cf80 commit d418003

5 files changed

Lines changed: 145 additions & 88 deletions

File tree

.agents

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.claude

.claude/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

AGENTS.md

Lines changed: 0 additions & 54 deletions
This file was deleted.

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CLAUDE.md

CLAUDE.md

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,100 @@
1-
AGENTS.md
1+
# Widget
2+
3+
Embeddable support widget customers drop into their own product via a script tag. Published to npm as `@marketrix.ai/widget`. Runs inside arbitrary host pages, so host-page safety, predictable runtime, and bundle size are first-class concerns.
4+
5+
Stack: React 19 (peer dep), Vite 8, TypeScript 6, Tailwind CSS 4 (`@tailwindcss/vite`), Zod 4, oRPC 1, `@rrweb/record` for session recording, `@base-ui/react` for primitives. Output is a single ESM bundle `dist/widget.mjs` plus a classic `loader.js`.
6+
7+
Dev server: `npm start` on port **9001** (`http://widget.marketrix.localhost`). Port is overridable via `PORT` / `VITE_PORT`.
8+
9+
## Commands
10+
11+
```bash
12+
npm start # vite dev server on :9001
13+
npm run build # vite build → dist/widget.mjs (terser) + tsc declarations
14+
npm run code:check # tsc --noEmit && eslint && prettier --check (one-shot gate)
15+
npm run code:fix # eslint --fix && prettier --write
16+
npm run type-check # tsc --noEmit (alias: check)
17+
npm run lint # eslint --fix (max-warnings 200); lint:check = max-warnings 0
18+
npm run format:check # prettier --check
19+
npm run test:run # vitest run (jsdom + Testing Library + axe)
20+
npm run test # vitest watch (test:ui = watch, test:coverage = v8)
21+
npm run visual:check # scripts/visual-check.mjs — gates on rendered UI
22+
npm run a11y:check # scripts/a11y-check.mjs — gates on accessibility
23+
npm run bundle:check # scripts/bundle-check.mjs — gates on bundle size
24+
npm run tag <version> # scripts/release.sh — see Release below
25+
```
26+
27+
**Pre-handoff gates** (mirrors `ci.yml` `validate` job): `type-check`, `lint`, `build`, `format:check`, `test:run`, then `visual:check` + `a11y:check` + `bundle:check`. Git hooks (lefthook) run type-check + autofixing lint, but they are not a substitute — run the full set.
28+
29+
## Runtime model
30+
31+
- Mounts into a **closed Shadow DOM** (`attachShadow({ mode: 'closed' })` in `src/utils/bootstrap.tsx`) to prevent host CSS/DOM leakage. CSS is injected into the shadow root via `vite-plugin-css-injected-by-js` (no external stylesheet).
32+
- `window.__mtx` is the **singleton guard** — duplicate/concurrent `initWidget` calls are deduplicated.
33+
- Three credential modes (auto-detected by `mountWidget`):
34+
- **Production**: `mtxId` + `mtxKey`
35+
- **Dev**: `mtxApp` (application id) + `mtxAgent` (agent id)
36+
- **Preview**: rendered via the `<MarketrixWidget>` React component with inline `settings`
37+
- All modes require `mtxApiHost`.
38+
39+
## Transport (widget ↔ api)
40+
41+
Two typed oRPC procedures, both defined in `src/sdk/contracts/widget.ts`:
42+
43+
- **`widgetStream`** — GET `/widget/stream`, an SSE `eventIterator(WidgetEventSchema)`. Server → widget events.
44+
- **`widgetMessage`** — POST `/widget/message`, body `{ chat_id, command: WidgetCommandSchema }`. Widget → server commands.
45+
46+
Both schemas are **discriminated unions on `type`**:
47+
48+
- `WidgetEvent` types: `registered`, `pong`, `heartbeat`, `chat/response`, `chat/error`, `task/status`, `tool/call`.
49+
- `WidgetCommand` types: `chat/tell`, `chat/show`, `chat/do`, `chat/stop`, `tool/response`, `ping`, `rrweb/metadata`, `rrweb/events`.
50+
51+
**Task status vocabulary (Wave 14):** `task/status.status` is `z.enum(['running', 'completed', 'failed', 'stopped', 'has_question'])`. Legacy `'started'` / `'in_progress'` were dropped — the widget now emits/consumes `'running'`. Matches the agent-side `SimulationTaskStatus` / `QATaskStatus`.
52+
53+
Interaction modes map to commands: **Tell** = `chat/tell` (explain), **Show** = `chat/show` (`tool/call` with `mode: 'show'`, visual highlighting), **Do** = `chat/do` (`tool/call` with `mode: 'do'`, performs browser actions).
54+
55+
## SDK mirror (must stay in sync)
56+
57+
The widget's SDK is a **scoped mirror** of the API contract, generated from the source of truth in the `api` repo:
58+
59+
| Source of truth (`api` repo) | Widget mirror |
60+
|---|---|
61+
| `api/contracts/widget.ts` + `contracts/*.ts` | `widget/src/sdk/contracts/*.ts` |
62+
| `api/sdk/widget.ts` (scoped aggregate) | `widget/src/sdk/contract.ts` |
63+
64+
The widget mirror is per-domain contract fragments under `src/sdk/contracts/` (`widget.ts`, `agent.ts`, `application.ts`, `chat.ts`, `entities.ts`, `common.ts`, `activityLog.ts`) — there is **no** `src/sdk/routes.ts` or `src/sdk/schema.ts` (those are stale references). `src/sdk/contract.ts` assembles the `widgetContract` object; `src/sdk/index.ts` exports the oRPC client (`sdk`) plus `configureSdk()` and re-exports `WidgetEventSchema`, `WidgetSettingsDataSchema`, and contract types.
65+
66+
Drift is enforced by `.github/workflows/contract-drift.yml`: it sparse-checkouts `api@dev` and runs api's `scripts/sync-consumers.mjs widget --check`. **It requires the `CONTRACTS_READ_TOKEN` repo/org secret** (fine-grained PAT, Contents:read on `Marketrix-ai/api`) or it fails fast. Don't hand-edit `src/sdk/contracts/*` — regenerate from the api side and run the sync.
67+
68+
## Key services (`src/services/`)
69+
70+
- `StreamClient.ts` — SSE lifecycle: registration, auth-failure handling, exponential-backoff reconnects.
71+
- `SessionRecorder.ts` — rrweb batching + POST flush. Thresholds: flush every **500 ms** (`FLUSH_INTERVAL_MS`) or at **50 KB** queued (`FLUSH_SIZE_THRESHOLD`); batches capped at **500 KB** (`MAX_BATCH_BYTES`, stays under the API body-parser limit); queue capped at 500 events; drops after 5 consecutive flush failures. Don't change these without updating the API's expectations.
72+
- `ToolService.ts` / `ShowModeService.ts` / `DomService.ts` — tool execution, Show-mode highlighting, host-page DOM interaction.
73+
- `ChatService.ts`, `SessionManager.ts`, `StorageService.ts`, `ConfigManager.ts`, `ValidationService.ts`, `WidgetService.ts`, `ApiService.ts`, `ScreenShareService.ts`.
74+
75+
## Structure
76+
77+
- `src/components/` — UI (`base/`, `blocks/`, `chat/`, `navigation/`, `ui/`, `views/`).
78+
- `src/design-system/` — design tokens + primitives (keep token usage consistent).
79+
- `src/services/` — see above. `src/hooks/`, `src/context/`, `src/utils/`, `src/lib/` — client state + helpers.
80+
- `src/sdk/` — oRPC client + contract mirror (see above).
81+
- `src/index.tsx` — public entry: `initWidget`, `mountWidget`, `unmountWidget`, `updateMarketrixConfig`, `getCurrentConfig`, `startRecording`/`stopRecording`/`getRecordingState`, `MarketrixWidget`.
82+
- `src/test/` + `src/**/__tests__/` — vitest setup, fixtures, a11y helpers. Name tests `*.test.ts(x)` near the feature.
83+
- `public/loader.js` — classic script-tag loader. `dist/` — generated only.
84+
85+
## Release
86+
87+
`@marketrix.ai/widget` is npm-published. Version is currently `3.8.9`.
88+
89+
1. `npm run tag <version>` (e.g. `npm run tag 3.8.10`) runs `scripts/release.sh`: bumps `package.json`, **`npm install` to refresh `package-lock.json`**, `npm run build`, commits `package.json` + `package-lock.json` as `chore(widget): release vX`, and creates annotated tag `vX`.
90+
2. Push: `git push origin HEAD && git push origin v<version>`.
91+
3. The `v*` tag triggers `ci.yml`: `build` job → `marketrix.azurecr.io/widget:<version>` (v-prefix stripped for image tag), `publish` job → npm (skipped if that version already exists, so sync-only tags are safe).
92+
4. Bumping the app's pinned version: `cd ../app && npm install @marketrix.ai/widget@latest`, then deploy widget + app together via the centralized `deploy.yml` in `infra`.
93+
94+
**Lockfile rule:** any version bump or dependency change must run `npm install` and commit `package-lock.json` alongside `package.json`. `npm run tag` does this for you.
95+
96+
## Conventions
97+
98+
- TS, 2-space indent, single quotes, semicolons, trailing commas, ~120-char lines. `type` imports, sorted imports (simple-import-sort). `PascalCase` components/services/context, `useCamelCase` hooks, `camelCase` utils.
99+
- Don't develop on `dev` — use a worktree/feature branch. Link the PR with `Closes #N`. Issue/PR body is the scope source of truth.
100+
- Prefer extending shared services/utils over one-off logic in a component.

README.md

Lines changed: 42 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -152,14 +152,7 @@ interface MarketrixConfig {
152152

153153
### Prerequisites
154154

155-
| Workflow | Trigger | Action |
156-
| -------------- | -------------------------------- | ------------------------------------------------------------------- |
157-
| `validate.yml` | Push / PR to `dev`, `main` | Type check, lint, format, tests, build, visual, a11y, bundle checks |
158-
| `build.yml` | Tag push (`v*`) or push to `dev` | Build Docker image, push to ACR; publish to npm on tag |
159-
160-
Image builds produce `marketrix.azurecr.io/widget:{version}`. Tag pushes also publish `@marketrix.ai/widget` to npm. Deployment to dev/prod is handled by the centralized deploy workflow (e.g. `deploy.yml` in infra). Dev branch pushes do not build images.
161-
162-
- Node.js 18+
155+
- Node.js 24 (CI pins `node-version: 24`)
163156
- npm
164157

165158
### Setup
@@ -168,24 +161,27 @@ Image builds produce `marketrix.azurecr.io/widget:{version}`. Tag pushes also pu
168161
git clone <repository-url>
169162
cd widget
170163
npm install
171-
npm start # dev server on port 5174
172-
npm run build # production build
164+
npm start # dev server on port 9001 (widget.marketrix.localhost)
165+
npm run build # production build → dist/widget.mjs
173166
```
174167

175168
### Project Structure
176169

177170
```
178171
widget/
179172
├── src/
180-
│ ├── components/ # React components (chat, layout, UI, input)
173+
│ ├── components/ # React components (base, blocks, chat, navigation, ui, views)
174+
│ ├── design-system/ # design tokens + primitives
181175
│ ├── context/ # WidgetContext provider
182176
│ ├── hooks/ # Custom React hooks
183-
│ ├── services/ # Core services (stream, chat, recording, etc.)
184-
│ ├── sdk/ # oRPC client + contract mirrors
177+
│ ├── services/ # Core services (StreamClient, ChatService, SessionRecorder, ToolService, …)
178+
│ ├── sdk/ # oRPC client + scoped contract mirror (contract.ts + contracts/*)
185179
│ ├── types/ # TypeScript types
186-
│ ├── utils/ # Utility functions
187-
│ ├── constants/ # Config constants and theme tokens
188-
│ └── index.tsx # Main entry point
180+
│ ├── utils/ # Utility functions (incl. bootstrap.tsx — closed Shadow DOM mount)
181+
│ ├── constants/ # Config constants
182+
│ ├── lib/ # shared helpers
183+
│ └── index.tsx # Main entry point (public API)
184+
├── public/loader.js # classic script-tag loader
189185
├── vite.config.ts
190186
├── tsconfig.json
191187
└── package.json
@@ -202,31 +198,44 @@ Output files:
202198

203199
## CI/CD
204200

205-
| Workflow | Trigger | Action |
206-
| -------------- | ------------------ | ----------------------------------------------- |
207-
| `validate.yml` | Push to `dev` / PR | Type check, lint, build |
208-
| `build.yml` | Tag push (`v*`) | Build Docker image, push to ACR, publish to npm |
201+
Single workflow `ci.yml` with three jobs:
202+
203+
| Job | Trigger | Action |
204+
| --------- | -------------------- | ------------------------------------------------------------------------------- |
205+
| `validate` | Push / PR to `dev` | type-check, lint, build, format:check, test:run, visual/a11y/bundle checks |
206+
| `build` | Tag push (`v*`) | Build Docker image → `marketrix.azurecr.io/widget:{version}` (v-prefix stripped) |
207+
| `publish` | Tag push (`v*`) | `npm publish @marketrix.ai/widget` (skipped if version already on registry) |
208+
209+
`contract-drift.yml` fails PRs whose `src/sdk/` mirror has drifted from `Marketrix-ai/api` (needs the `CONTRACTS_READ_TOKEN` secret). Dev branch pushes do not build images. Deployment to dev/prod is handled by the centralized `deploy.yml` in `infra`.
210+
211+
### Release
212+
213+
```bash
214+
npm run tag <version> # bumps package.json, refreshes lockfile, builds, commits, tags vX
215+
git push origin HEAD && git push origin v<version>
216+
```
209217

210218
## Dependencies
211219

212-
### Production
220+
### Production (peer + runtime)
213221

214-
- `react` / `react-dom` v19 (peer dependency)
215-
- `@rrweb/record` - Session recording
216-
- `@orpc/client` / `@orpc/contract` v1 - Type-safe API client (oRPC)
217-
- `react-icons` - Icons
218-
- `zod` - Schema validation
222+
- `react` / `react-dom` ^19 — peer dependency
223+
- `@rrweb/record` — session recording
224+
- `@orpc/client` / `@orpc/contract` ^1 — type-safe API client (oRPC)
225+
- `@base-ui/react` — UI primitives
226+
- `zod` ^4 — schema validation
227+
- `tailwind-merge` — class merging
219228

220229
### Development
221230

222-
- Vite 6
223-
- Tailwind CSS v4 (via `@tailwindcss/vite` plugin)
224-
- TypeScript 5
225-
- Vitest + Testing Library (unit and integration tests)
226-
- ESLint + Prettier
231+
- Vite 8
232+
- Tailwind CSS 4 (via `@tailwindcss/vite` plugin)
233+
- TypeScript 6
234+
- Vitest + Testing Library + axe (unit, integration, a11y)
235+
- ESLint 10 + Prettier
227236
- Terser for production minification
228237

229-
**Quality gates (run before PR):** `npm run type-check`, `npm run lint:check`, `npm run format:check`, `npm run test:run`, `npm run build`, `npm run visual:check`, `npm run a11y:check`, `npm run bundle:check`. See `.github/pull_request_template.md` and `docs/release-ui-checklist.md`.
238+
**Quality gates (run before PR):** `npm run code:check` (type-check + lint + format), `npm run test:run`, `npm run build`, then `npm run visual:check`, `npm run a11y:check`, `npm run bundle:check`.
230239

231240
## License
232241

@@ -237,4 +246,4 @@ Apache License 2.0 - see LICENSE file for details.
237246
For support and questions, please contact the Marketrix team or create an issue
238247
in the repository.
239248

240-
[Back to top](#marketrix-in-app-support-widget)
249+
[Back to top](#marketrix-widget)

0 commit comments

Comments
 (0)