mirror of
https://github.com/Novaloop-AG/healthchat-web.git
synced 2026-10-31 16:23:03 +00:00
docs: rewrite CLAUDE.md for pnpm/Nx monorepo
This commit is contained in:
@@ -2,22 +2,35 @@
|
||||
|
||||
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
|
||||
|
||||
- Node.js >= 22.18
|
||||
- Yarn 1.x (classic)
|
||||
- Node.js: `.node-version` pins **24** (package.json `engines` allows `>=22.18`)
|
||||
- pnpm (the repo uses a `pnpm-lock.yaml` and a catalog for shared dependency versions)
|
||||
|
||||
## Commands
|
||||
|
||||
### Setup
|
||||
- `yarn install` - Install dependencies
|
||||
- Copy `config.sample.json` to `config.json` and configure (see docs/config.md)
|
||||
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`.
|
||||
|
||||
### Development
|
||||
- `yarn start` - Run development server on http://localhost:8080
|
||||
- `yarn start:https` - Run development server with HTTPS
|
||||
- `yarn build` - Production build (outputs to webapp/)
|
||||
- `yarn dist` - Create distribution tarball
|
||||
### Setup
|
||||
- `pnpm install` — install dependencies (runs `scripts/pnpm-link.ts` postinstall, see SDK linking below)
|
||||
- Copy `apps/web/config.sample.json` to `apps/web/config.json` and configure (see `docs/config.md`)
|
||||
|
||||
### 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:
|
||||
```bash
|
||||
@@ -25,93 +38,84 @@ sudo sysctl fs.inotify.max_user_watches=131072
|
||||
sudo sysctl fs.inotify.max_user_instances=512
|
||||
```
|
||||
|
||||
### Testing
|
||||
- `yarn test` - Run Jest unit tests
|
||||
- `yarn test:playwright` - Run Playwright e2e tests
|
||||
- `yarn test:playwright:open` - Open Playwright test UI
|
||||
- `yarn coverage` - Run tests with coverage reporting
|
||||
### Testing (from `apps/web`)
|
||||
- `pnpm test` — Jest unit tests (`nx test:unit`)
|
||||
- `pnpm test path/to/file.test.ts` — run a single Jest test file
|
||||
- `pnpm test:playwright` — Playwright e2e tests
|
||||
- `pnpm test:playwright:open` — Playwright UI
|
||||
- `pnpm coverage` — unit tests with coverage
|
||||
|
||||
To run a single test file:
|
||||
- `yarn test path/to/test-file.test.ts`
|
||||
- `yarn test:playwright path/to/e2e-test.ts`
|
||||
Note: `apps/desktop` unit tests use **Vitest** (`pnpm --filter element-desktop test:unit`), not Jest.
|
||||
|
||||
### Code Quality
|
||||
- `yarn lint` - Run all linters (TypeScript, ESLint, Stylelint)
|
||||
- `yarn lint:js-fix` - Auto-fix ESLint issues
|
||||
- `yarn lint:types` - TypeScript type checking only
|
||||
- `yarn lint:style` - Check CSS/PostCSS styles
|
||||
- `pnpm lint` (root) — full lint across all workspaces: types, prettier, eslint, stylelint, GH workflows, knip
|
||||
- `pnpm --filter element-web lint:types` — TypeScript check only (via Nx)
|
||||
- `pnpm --filter element-web lint:js-fix` — auto-fix ESLint
|
||||
- `pnpm --filter element-web lint:style` — Stylelint on `res/css/**/*.pcss`
|
||||
|
||||
### Utilities
|
||||
- `yarn make-component` - Scaffold new React component
|
||||
- `yarn i18n` - Manage translations
|
||||
- `yarn storybook` - Run Storybook on port 6007
|
||||
- `pnpm i18n` (root or per-package) — regenerate/sort/lint translation strings
|
||||
- `pnpm --filter @element-hq/web-shared-components storybook` — Storybook on port 6007
|
||||
|
||||
## 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
|
||||
The application follows a hierarchical component structure:
|
||||
- `MatrixChat` - Root component managing the entire application state
|
||||
- `LeftPanel` - Room list, spaces, and navigation
|
||||
- `MainSplit` - Central room view with messages and input
|
||||
- `RightPanel` - Member list, room info, and contextual panels
|
||||
Hierarchical layout:
|
||||
- `MatrixChat` — root component managing whole-application state
|
||||
- `LeftPanel` — room list, spaces, navigation
|
||||
- `MainSplit` — central room view with messages and composer
|
||||
- `RightPanel` — member list, room info, contextual panels
|
||||
|
||||
Components are organized in `/src/components/`:
|
||||
- `/structures/` - Major layout components
|
||||
- `/views/` - Reusable UI components grouped by function (auth, dialogs, messages, rooms, settings)
|
||||
Components live in `apps/web/src/components/`:
|
||||
- `structures/` — major layout components (these use React classes)
|
||||
- `views/` — reusable UI grouped by function (auth, dialogs, messages, rooms, settings)
|
||||
|
||||
### State Management
|
||||
Uses Flux architecture with:
|
||||
- Centralized dispatcher in `/src/dispatcher/`
|
||||
- Stores in `/src/stores/` as singletons (access via `FooStore.instance`)
|
||||
- Dispatch actions: `dis.dispatch({ action: Action.FOO, ...payload })` or `dis.fire(Action.FOO)` for action-only
|
||||
Flux architecture:
|
||||
- Centralized dispatcher in `apps/web/src/dispatcher/`
|
||||
- Stores in `apps/web/src/stores/` as singletons (access via `FooStore.instance`)
|
||||
- Dispatch: `dis.dispatch({ action: Action.FOO, ...payload })` or `dis.fire(Action.FOO)` for action-only
|
||||
|
||||
### Styling
|
||||
- PostCSS files with `.pcss` extension
|
||||
- BEM-like naming: `mx_ComponentName_element`
|
||||
- Component styles co-located with components (e.g., `_MessageTile.pcss`)
|
||||
- PostCSS `.pcss` files, BEM-like naming `mx_ComponentName_element`
|
||||
- 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
|
||||
|
||||
### Matrix Integration
|
||||
- Uses `matrix-js-sdk` for all Matrix protocol operations
|
||||
- Client instance accessed via `MatrixClientPeg`
|
||||
- Room and event handling through SDK abstractions
|
||||
- `matrix-js-sdk` for all Matrix protocol operations
|
||||
- Client accessed via `MatrixClientPeg`
|
||||
- Room/event handling through SDK abstractions
|
||||
|
||||
### Module System
|
||||
Plugin architecture in `/src/modules/`:
|
||||
- Allows runtime extension of functionality
|
||||
- Module API for registering custom components and handlers
|
||||
Runtime plugin architecture (`apps/web/module_system/`, public API in `packages/module-api`):
|
||||
- `prebuild:module_system` reads `apps/web/build_config.yaml` and generates `apps/web/src/modules.js`
|
||||
- HealthChat ships the `healthchat-workspace` module (see release section)
|
||||
|
||||
### Testing Patterns
|
||||
- Unit tests in `/test/unit-tests/` using Jest
|
||||
- E2E tests in `/playwright/e2e/` using Playwright
|
||||
- Mock Matrix client and SDK extensively in tests
|
||||
- Component tests via Storybook
|
||||
- Web unit tests in `apps/web/test/unit-tests/` (Jest)
|
||||
- E2E tests in `apps/web/playwright/e2e/` (Playwright)
|
||||
- Mock the Matrix client/SDK extensively in tests
|
||||
- Component stories/visual tests via Storybook in `packages/shared-components`
|
||||
|
||||
### Important Conventions
|
||||
- TypeScript strict mode - always use explicit types
|
||||
- Functional components with hooks preferred over class components (except "structures" which use classes)
|
||||
- Translations use `_t()` function with hierarchical keys
|
||||
- 4-space indentation, 120 character line limit
|
||||
- Component files: UpperCamelCase, utilities: kebab-case
|
||||
- Use `Optional<T>` type instead of truly optional parameters when callers should explicitly acknowledge missing values
|
||||
- CSS class names must be prefixed with `mx_` and match component name (e.g., `mx_RoomTile`)
|
||||
- TypeScript strict mode — always use explicit types
|
||||
- Functional components with hooks preferred over class components (except `structures/` which use classes)
|
||||
- Translations use `_t()` with hierarchical keys
|
||||
- 4-space indentation, 120-character line limit
|
||||
- Component files: UpperCamelCase; utilities: kebab-case
|
||||
- Use `Optional<T>` instead of truly optional params when callers should explicitly acknowledge missing values
|
||||
- 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`)
|
||||
- Use `jest-matrix-react` instead of `@testing-library/react` for component tests
|
||||
- No `React.forwardRef` - use ref props directly instead
|
||||
- Use UIStore for window dimensions instead of `window.innerHeight`/`window.innerWidth`
|
||||
- Use Media helper for MXC URL handling instead of direct `mxcUrlToHttp` calls
|
||||
- No `React.forwardRef` — use ref props directly
|
||||
- Use `UIStore` for window dimensions instead of `window.innerHeight`/`window.innerWidth`
|
||||
- Use the `Media` helper for MXC URL handling instead of direct `mxcUrlToHttp` calls
|
||||
|
||||
### Linked Development with matrix-js-sdk
|
||||
For developing against local SDK changes:
|
||||
```bash
|
||||
# In matrix-js-sdk directory
|
||||
yarn link && yarn install
|
||||
|
||||
# In element-web directory
|
||||
yarn link matrix-js-sdk && yarn install && yarn start
|
||||
```
|
||||
`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`.
|
||||
|
||||
### 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.
|
||||
|
||||
Reference in New Issue
Block a user