mirror of
https://github.com/Novaloop-AG/healthchat-web.git
synced 2026-10-31 08:15:07 +00:00
137 lines
8.9 KiB
Markdown
137 lines
8.9 KiB
Markdown
# CLAUDE.md
|
|
|
|
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: `.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
|
|
|
|
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`.
|
|
|
|
### 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
|
|
sudo sysctl fs.inotify.max_user_watches=131072
|
|
sudo sysctl fs.inotify.max_user_instances=512
|
|
```
|
|
|
|
### 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 (the `--` forwards args to Jest; or `cd apps/web && npx jest path/...`)
|
|
- `pnpm test:playwright` — Playwright e2e tests
|
|
- `pnpm test:playwright:open` — Playwright UI
|
|
- `pnpm test:playwright:screenshots` — update Playwright screenshot snapshots
|
|
- `pnpm coverage` — unit tests with coverage
|
|
|
|
Note: `apps/desktop` unit tests use **Vitest** (`pnpm --filter element-desktop test:unit`), not Jest.
|
|
|
|
### Code Quality
|
|
- `pnpm lint` (root) — full lint across all workspaces: types, prettier, eslint, stylelint, GH workflows, knip
|
|
- `pnpm --filter element-web lint` — package-local shorthand for `lint:types && lint:js && lint:style`
|
|
- `pnpm --filter element-web lint:types` — TypeScript check only (via Nx)
|
|
- `pnpm --filter element-web lint:js` — ESLint check (`lint:js-fix` auto-fixes)
|
|
- `pnpm --filter element-web lint:style` — Stylelint on `res/css/**/*.pcss`
|
|
- `pnpm lint:knip` (root) — unused deps/exports; `pnpm lint:workflows` — validate GH Actions YAML. Both run as part of `pnpm lint` and gate CI.
|
|
|
|
### Utilities
|
|
- `pnpm i18n` (root or per-package) — regenerate/sort/lint translation strings; chains `i18n:sort`, `i18n:lint`, and `i18n:diff` (run any one directly when only that step is needed)
|
|
- `pnpm --filter @element-hq/web-shared-components storybook` — Storybook on port 6007
|
|
|
|
## Architecture
|
|
|
|
Element Web is a Matrix client built with React + TypeScript, customized here as "HealthChat". The architecture below describes `apps/web/src/`.
|
|
|
|
### Component Structure
|
|
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 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)
|
|
|
|
Other recurring `apps/web/src/` layers worth knowing:
|
|
- `customisations/` — Element customization hooks (e.g. `Media.ts`, `WidgetPermissions.ts`) — the sanctioned override points
|
|
- `viewmodels/` — view logic separated from React components, consumed by `structures/` classes
|
|
- `async-components/` — code-split / lazy-loaded mirrors of components (e.g. `ErrorView.tsx`)
|
|
|
|
### State Management
|
|
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 `.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
|
|
- `matrix-js-sdk` for all Matrix protocol operations
|
|
- Client accessed via `MatrixClientPeg`
|
|
- Room/event handling through SDK abstractions
|
|
|
|
### Module System
|
|
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` (empty by default in this fork — no committed `build_config.yaml`)
|
|
- In production, modules are loaded at runtime from `config.json`'s `modules` array, not via the build-time `modules.js` path
|
|
- HealthChat ships the `healthchat-workspace` module (see release section); its version is pinned in `.healthchat-workspace-version`
|
|
|
|
### HealthChat fork specifics
|
|
Conventions unique to this fork that span multiple files:
|
|
- **Branding defaults**: hardcoded in `apps/web/src/SdkConfig.ts` (`brand: "HealthChat"`, mobile app-store URLs); runtime config in `apps/web/config.json` (homeserver `matrix.healthchat.ch`, custom "HealthChat Light" theme). `config.sample.json` is the dev template — copy it to `config.json`.
|
|
- **Widget auto-approval**: widgets served from `api.healthchat.ch` bypass permission dialogs and hide revoke/minimize controls. Logic lives in `apps/web/src/stores/widgets/ElementWidgetDriver.ts`, `apps/web/src/components/views/elements/AppTile.tsx`, and `.../context_menus/WidgetContextMenu.tsx`; base URL comes from the `ch.healthchat.api_base_url` config key.
|
|
- **Desktop deep-linking**: scheme is `healthchat://` (`apps/desktop/src/protocol.ts`), with the SSO session passed via the `healthchat-desktop-ssoid` param. Desktop variant config (and its build runbook) lives under `apps/desktop/element.io/healthchat/` (`config.json`, `build.json`, `README`).
|
|
|
|
### Testing Patterns
|
|
- 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()` 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
|
|
- 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
|
|
`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` (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.
|