docs: rewrite CLAUDE.md for pnpm/Nx monorepo

This commit is contained in:
2026-06-06 15:13:59 +02:00
parent 5f09f58a82
commit f0c6c17e4a
+74 -70
View File
@@ -2,22 +2,35 @@
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Repository layout
This is a **pnpm + Nx monorepo** (not Yarn — the older single-package layout is gone). Workspaces are defined in `pnpm-workspace.yaml`:
- `apps/web` (`element-web`) — the browser client. **This is where almost all feature work happens.** Source is `apps/web/src/` (not a top-level `/src/`).
- `apps/desktop` (`element-desktop`) — the Electron wrapper. Uses Vitest for unit tests and `hak` for native modules.
- `packages/module-api` (`@element-hq/element-web-module-api`) — public API surface for runtime modules.
- `packages/shared-components` (`@element-hq/web-shared-components`) — shared React components; home of Storybook.
- `packages/playwright-common`, `packages/vite-common` — shared test/build helpers.
Build orchestration is Nx (`nx.json`); most `apps/web` scripts (`build`, `start`, `test`, `lint:types`) delegate to Nx targets defined in `apps/web/project.json`, which handle prebuild steps (`prebuild:module_system`, `prebuild:rethemendex`) automatically.
## Prerequisites ## Prerequisites
- Node.js >= 22.18 - Node.js: `.node-version` pins **24** (package.json `engines` allows `>=22.18`)
- Yarn 1.x (classic) - pnpm (the repo uses a `pnpm-lock.yaml` and a catalog for shared dependency versions)
## Commands ## Commands
### Setup Run package-scoped commands from inside the package dir (e.g. `cd apps/web`) or from the root with `pnpm --filter element-web <script>`. Root-level scripts (`pnpm lint`, `pnpm i18n`) fan out across all workspaces via `pnpm -r`.
- `yarn install` - Install dependencies
- Copy `config.sample.json` to `config.json` and configure (see docs/config.md)
### Development ### Setup
- `yarn start` - Run development server on http://localhost:8080 - `pnpm install` — install dependencies (runs `scripts/pnpm-link.ts` postinstall, see SDK linking below)
- `yarn start:https` - Run development server with HTTPS - Copy `apps/web/config.sample.json` to `apps/web/config.json` and configure (see `docs/config.md`)
- `yarn build` - Production build (outputs to webapp/)
- `yarn dist` - Create distribution tarball ### Development (from `apps/web`)
- `pnpm start` — dev server on http://localhost:8080 (`nx start`)
- `pnpm build` — production build, outputs to `apps/web/webapp/`
- `pnpm dist` — distribution tarball (`./scripts/package.sh`)
**Linux note**: If builds fail silently or with `EMFILE: too many open files`, increase inotify limits: **Linux note**: If builds fail silently or with `EMFILE: too many open files`, increase inotify limits:
```bash ```bash
@@ -25,93 +38,84 @@ sudo sysctl fs.inotify.max_user_watches=131072
sudo sysctl fs.inotify.max_user_instances=512 sudo sysctl fs.inotify.max_user_instances=512
``` ```
### Testing ### Testing (from `apps/web`)
- `yarn test` - Run Jest unit tests - `pnpm test` — Jest unit tests (`nx test:unit`)
- `yarn test:playwright` - Run Playwright e2e tests - `pnpm test path/to/file.test.ts` — run a single Jest test file
- `yarn test:playwright:open` - Open Playwright test UI - `pnpm test:playwright` — Playwright e2e tests
- `yarn coverage` - Run tests with coverage reporting - `pnpm test:playwright:open` — Playwright UI
- `pnpm coverage` — unit tests with coverage
To run a single test file: Note: `apps/desktop` unit tests use **Vitest** (`pnpm --filter element-desktop test:unit`), not Jest.
- `yarn test path/to/test-file.test.ts`
- `yarn test:playwright path/to/e2e-test.ts`
### Code Quality ### Code Quality
- `yarn lint` - Run all linters (TypeScript, ESLint, Stylelint) - `pnpm lint` (root) — full lint across all workspaces: types, prettier, eslint, stylelint, GH workflows, knip
- `yarn lint:js-fix` - Auto-fix ESLint issues - `pnpm --filter element-web lint:types` — TypeScript check only (via Nx)
- `yarn lint:types` - TypeScript type checking only - `pnpm --filter element-web lint:js-fix` — auto-fix ESLint
- `yarn lint:style` - Check CSS/PostCSS styles - `pnpm --filter element-web lint:style` — Stylelint on `res/css/**/*.pcss`
### Utilities ### Utilities
- `yarn make-component` - Scaffold new React component - `pnpm i18n` (root or per-package) — regenerate/sort/lint translation strings
- `yarn i18n` - Manage translations - `pnpm --filter @element-hq/web-shared-components storybook` — Storybook on port 6007
- `yarn storybook` - Run Storybook on port 6007
## Architecture ## Architecture
This is Element Web, a Matrix client built with React and TypeScript, customized as "HealthChat". Key architectural patterns: Element Web is a Matrix client built with React + TypeScript, customized here as "HealthChat". The architecture below describes `apps/web/src/`.
### Component Structure ### Component Structure
The application follows a hierarchical component structure: Hierarchical layout:
- `MatrixChat` - Root component managing the entire application state - `MatrixChat` — root component managing whole-application state
- `LeftPanel` - Room list, spaces, and navigation - `LeftPanel` — room list, spaces, navigation
- `MainSplit` - Central room view with messages and input - `MainSplit` — central room view with messages and composer
- `RightPanel` - Member list, room info, and contextual panels - `RightPanel` — member list, room info, contextual panels
Components are organized in `/src/components/`: Components live in `apps/web/src/components/`:
- `/structures/` - Major layout components - `structures/` — major layout components (these use React classes)
- `/views/` - Reusable UI components grouped by function (auth, dialogs, messages, rooms, settings) - `views/` — reusable UI grouped by function (auth, dialogs, messages, rooms, settings)
### State Management ### State Management
Uses Flux architecture with: Flux architecture:
- Centralized dispatcher in `/src/dispatcher/` - Centralized dispatcher in `apps/web/src/dispatcher/`
- Stores in `/src/stores/` as singletons (access via `FooStore.instance`) - Stores in `apps/web/src/stores/` as singletons (access via `FooStore.instance`)
- Dispatch actions: `dis.dispatch({ action: Action.FOO, ...payload })` or `dis.fire(Action.FOO)` for action-only - Dispatch: `dis.dispatch({ action: Action.FOO, ...payload })` or `dis.fire(Action.FOO)` for action-only
### Styling ### Styling
- PostCSS files with `.pcss` extension - PostCSS `.pcss` files, BEM-like naming `mx_ComponentName_element`
- BEM-like naming: `mx_ComponentName_element` - Styles co-located with components (e.g. `_MessageTile.pcss`)
- Component styles co-located with components (e.g., `_MessageTile.pcss`) - `res/css/_components.pcss` is **generated** by the `rethemendex` prebuild step — don't hand-edit it
- Theming via CSS custom properties - Theming via CSS custom properties
### Matrix Integration ### Matrix Integration
- Uses `matrix-js-sdk` for all Matrix protocol operations - `matrix-js-sdk` for all Matrix protocol operations
- Client instance accessed via `MatrixClientPeg` - Client accessed via `MatrixClientPeg`
- Room and event handling through SDK abstractions - Room/event handling through SDK abstractions
### Module System ### Module System
Plugin architecture in `/src/modules/`: Runtime plugin architecture (`apps/web/module_system/`, public API in `packages/module-api`):
- Allows runtime extension of functionality - `prebuild:module_system` reads `apps/web/build_config.yaml` and generates `apps/web/src/modules.js`
- Module API for registering custom components and handlers - HealthChat ships the `healthchat-workspace` module (see release section)
### Testing Patterns ### Testing Patterns
- Unit tests in `/test/unit-tests/` using Jest - Web unit tests in `apps/web/test/unit-tests/` (Jest)
- E2E tests in `/playwright/e2e/` using Playwright - E2E tests in `apps/web/playwright/e2e/` (Playwright)
- Mock Matrix client and SDK extensively in tests - Mock the Matrix client/SDK extensively in tests
- Component tests via Storybook - Component stories/visual tests via Storybook in `packages/shared-components`
### Important Conventions ### Important Conventions
- TypeScript strict mode - always use explicit types - TypeScript strict mode — always use explicit types
- Functional components with hooks preferred over class components (except "structures" which use classes) - Functional components with hooks preferred over class components (except `structures/` which use classes)
- Translations use `_t()` function with hierarchical keys - Translations use `_t()` with hierarchical keys
- 4-space indentation, 120 character line limit - 4-space indentation, 120-character line limit
- Component files: UpperCamelCase, utilities: kebab-case - Component files: UpperCamelCase; utilities: kebab-case
- Use `Optional<T>` type instead of truly optional parameters when callers should explicitly acknowledge missing values - Use `Optional<T>` instead of truly optional params when callers should explicitly acknowledge missing values
- CSS class names must be prefixed with `mx_` and match component name (e.g., `mx_RoomTile`) - CSS class names must be `mx_`-prefixed and match the component name (e.g. `mx_RoomTile`)
- Import matrix-js-sdk via `matrix-js-sdk/src/matrix` only (not `matrix-js-sdk` or `matrix-js-sdk/src`) - Import matrix-js-sdk via `matrix-js-sdk/src/matrix` only (not `matrix-js-sdk` or `matrix-js-sdk/src`)
- Use `jest-matrix-react` instead of `@testing-library/react` for component tests - Use `jest-matrix-react` instead of `@testing-library/react` for component tests
- No `React.forwardRef` - use ref props directly instead - No `React.forwardRef` — use ref props directly
- Use UIStore for window dimensions instead of `window.innerHeight`/`window.innerWidth` - Use `UIStore` for window dimensions instead of `window.innerHeight`/`window.innerWidth`
- Use Media helper for MXC URL handling instead of direct `mxcUrlToHttp` calls - Use the `Media` helper for MXC URL handling instead of direct `mxcUrlToHttp` calls
### Linked Development with matrix-js-sdk ### Linked Development with matrix-js-sdk
For developing against local SDK changes: `pnpm link` is **not** used (it mutates `package.json`/lockfile). Instead, the `postinstall` hook runs `scripts/pnpm-link.ts`, which reads a `.link-config` file of `DEPENDENCY=PATH` lines and replaces those `node_modules` entries with symlinks. To develop against a local SDK, add a line like `matrix-js-sdk=/abs/path/to/matrix-js-sdk` to `.link-config` (not committed) and re-run `pnpm install`.
```bash
# In matrix-js-sdk directory
yarn link && yarn install
# In element-web directory
yarn link matrix-js-sdk && yarn install && yarn start
```
### Releasing HealthChat ### Releasing HealthChat
Releases are cut by pushing a `healthchat-v<semver>` tag against `release/healthchat`, which triggers `.github/workflows/build-healthchat.yaml`. Release notes come from `HEALTHCHAT_CHANGES.md`; the plugin ref is pinned in `.healthchat-workspace-version`. Full runbook: `releasing-healthchat` skill. Releases are cut by pushing a `healthchat-v<semver>` tag against `release/healthchat`, which triggers `.github/workflows/build-healthchat.yaml` (web) and `build-healthchat-desktop.yaml` (desktop). Release notes come from `HEALTHCHAT_CHANGES.md` (kept separate from upstream `CHANGELOG.md`); the healthchat-workspace plugin ref is pinned in `.healthchat-workspace-version`. Full runbook: `releasing-healthchat` skill.