From 0885f56010ac74f03c88cfee41c885a3e53249a8 Mon Sep 17 00:00:00 2001 From: Nick Misasi Date: Wed, 14 Jan 2026 13:04:20 -0500 Subject: [PATCH] Add optional Claude.md orchestration for Webapp folder (#34668) * Add CLAUDE.md documentation files for webapp directories - Add root webapp CLAUDE.md with overview and build commands - Add channels CLAUDE.md with architecture and testing info - Add documentation for actions, components, selectors, utils - Add documentation for sass, tests, and mattermost-redux - Add platform documentation for client and types - Update .gitignore * Add CLAUDE docs and allow tracking * Clarify CLAUDE instructions for i18n workflow * Refactor webapp/CLAUDE.md into a nested hierarchy Decomposed the monolithic webapp/CLAUDE.md into focused, context-aware files distributed across the directory structure: - webapp/CLAUDE.md (Root overview) - webapp/channels/CLAUDE.md (Channels workspace) - webapp/channels/src/components/CLAUDE.md - webapp/channels/src/actions/CLAUDE.md - webapp/channels/src/selectors/CLAUDE.md - webapp/channels/src/packages/mattermost-redux/CLAUDE.md - webapp/platform/CLAUDE.md (Platform workspace) - webapp/platform/client/CLAUDE.md * Move files to optional, then add script to move them to proper claud.md --- .gitignore | 2 +- .../{CLAUDE.md => CLAUDE.OPTIONAL.md} | 0 enable-claude-docs.sh | 16 +++ webapp/CLAUDE.OPTIONAL.md | 98 +++++++++++++++++++ webapp/channels/CLAUDE.OPTIONAL.md | 73 ++++++++++++++ webapp/channels/src/CLAUDE.OPTIONAL.md | 36 +++++++ .../channels/src/actions/CLAUDE.OPTIONAL.md | 76 ++++++++++++++ .../src/components/CLAUDE.OPTIONAL.md | 85 ++++++++++++++++ webapp/channels/src/i18n/CLAUDE.OPTIONAL.md | 26 +++++ .../mattermost-redux/CLAUDE.OPTIONAL.md | 64 ++++++++++++ .../channels/src/plugins/CLAUDE.OPTIONAL.md | 29 ++++++ .../channels/src/reducers/CLAUDE.OPTIONAL.md | 28 ++++++ webapp/channels/src/sass/CLAUDE.OPTIONAL.md | 67 +++++++++++++ .../channels/src/selectors/CLAUDE.OPTIONAL.md | 63 ++++++++++++ webapp/channels/src/store/CLAUDE.OPTIONAL.md | 27 +++++ webapp/channels/src/tests/CLAUDE.OPTIONAL.md | 46 +++++++++ webapp/channels/src/types/CLAUDE.OPTIONAL.md | 28 ++++++ webapp/channels/src/utils/CLAUDE.OPTIONAL.md | 41 ++++++++ webapp/platform/CLAUDE.OPTIONAL.md | 45 +++++++++ webapp/platform/client/CLAUDE.OPTIONAL.md | 49 ++++++++++ webapp/platform/components/CLAUDE.OPTIONAL.md | 30 ++++++ webapp/platform/types/CLAUDE.OPTIONAL.md | 34 +++++++ webapp/scripts/CLAUDE.OPTIONAL.md | 25 +++++ 23 files changed, 987 insertions(+), 1 deletion(-) rename e2e-tests/playwright/{CLAUDE.md => CLAUDE.OPTIONAL.md} (100%) create mode 100755 enable-claude-docs.sh create mode 100644 webapp/CLAUDE.OPTIONAL.md create mode 100644 webapp/channels/CLAUDE.OPTIONAL.md create mode 100644 webapp/channels/src/CLAUDE.OPTIONAL.md create mode 100644 webapp/channels/src/actions/CLAUDE.OPTIONAL.md create mode 100644 webapp/channels/src/components/CLAUDE.OPTIONAL.md create mode 100644 webapp/channels/src/i18n/CLAUDE.OPTIONAL.md create mode 100644 webapp/channels/src/packages/mattermost-redux/CLAUDE.OPTIONAL.md create mode 100644 webapp/channels/src/plugins/CLAUDE.OPTIONAL.md create mode 100644 webapp/channels/src/reducers/CLAUDE.OPTIONAL.md create mode 100644 webapp/channels/src/sass/CLAUDE.OPTIONAL.md create mode 100644 webapp/channels/src/selectors/CLAUDE.OPTIONAL.md create mode 100644 webapp/channels/src/store/CLAUDE.OPTIONAL.md create mode 100644 webapp/channels/src/tests/CLAUDE.OPTIONAL.md create mode 100644 webapp/channels/src/types/CLAUDE.OPTIONAL.md create mode 100644 webapp/channels/src/utils/CLAUDE.OPTIONAL.md create mode 100644 webapp/platform/CLAUDE.OPTIONAL.md create mode 100644 webapp/platform/client/CLAUDE.OPTIONAL.md create mode 100644 webapp/platform/components/CLAUDE.OPTIONAL.md create mode 100644 webapp/platform/types/CLAUDE.OPTIONAL.md create mode 100644 webapp/scripts/CLAUDE.OPTIONAL.md diff --git a/.gitignore b/.gitignore index 473d44b7b37..b4e6be36708 100644 --- a/.gitignore +++ b/.gitignore @@ -161,5 +161,5 @@ docker-compose.override.yaml .env **/CLAUDE.local.md -CLAUDE.md +**/CLAUDE.md .cursorrules diff --git a/e2e-tests/playwright/CLAUDE.md b/e2e-tests/playwright/CLAUDE.OPTIONAL.md similarity index 100% rename from e2e-tests/playwright/CLAUDE.md rename to e2e-tests/playwright/CLAUDE.OPTIONAL.md diff --git a/enable-claude-docs.sh b/enable-claude-docs.sh new file mode 100755 index 00000000000..9d6a05dada3 --- /dev/null +++ b/enable-claude-docs.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# This script enables the optional Claude documentation by copying +# CLAUDE.OPTIONAL.md files to CLAUDE.md. +# CLAUDE.md files are gitignored, so they act as local-only documentation. + +echo "Enabling Claude documentation..." + +find . -name "CLAUDE.OPTIONAL.md" -not -path "*/node_modules/*" | while read -r file; do + target_file="${file%.OPTIONAL.md}.md" + echo "Copying $file to $target_file" + cp "$file" "$target_file" +done + +echo "Done! CLAUDE.md files are now active (and ignored by git). *NOTE: Re-running this script will overwrite any changes you'd made to the CLAUDE.md files. If you have an improvement, please change the relevant CLAUDE.OPTIONAL.md file instead, and submit a PR." + diff --git a/webapp/CLAUDE.OPTIONAL.md b/webapp/CLAUDE.OPTIONAL.md new file mode 100644 index 00000000000..1768819e4de --- /dev/null +++ b/webapp/CLAUDE.OPTIONAL.md @@ -0,0 +1,98 @@ +# CLAUDE.md + +Guidance for Claude Code when working inside `webapp/`. + +## Project Overview + +This is the Mattermost web app codebase, a React-based frontend application for the Mattermost collaboration platform. The repository is structured as an npm workspace monorepo with multiple packages, with the main application code in the `channels` package and shared platform code in `platform/*` packages. + +- **Primary workspace**: `channels/` (UI, Redux, routing). +- **Shared packages**: `platform/*`. +- **Scripts**: `webapp/scripts/` power dev server, builds, and localization flows. +- **Coding Standards**: Read `webapp/STYLE_GUIDE.md` for canonical standards; nested `CLAUDE.md` files cover directory-specific rules. + +## Core Commands + +| Task | Command | +| --- | --- | +| Install deps | `npm install` (includes postinstall build of platform packages) | +| Dev server (prod build watch) | `make run` | +| Dev server (webpack-dev-server) | `make dev` or `npm run dev-server --workspace=channels` | +| Build all workspaces | `make dist` or `npm run build` | +| Build Channels only | `npm run build --workspace=channels` | +| Tests | `make test` or `npm run test --workspace=channels` (use `test:watch`, `test:updatesnapshot` as needed) | +| Lint / Style | `make check-style`, `make fix-style`, `npm run check --workspace=channels`, `npm run fix --workspace=channels` | +| Type check | `make check-types` | +| Clean artifacts | `make clean` or `npm run clean --workspaces --if-present` | + +## Top-Level Directory Map + +- `channels/` – Channels workspace. See `channels/CLAUDE.md`. + - `src/` – App source with further scoped guides (components, actions, selectors, reducers, store, sass, i18n, tests, utils, types, plugins, packages/mattermost-redux). +- `platform/` – Shared packages (`client`, `components`, `types`, `eslint-plugin`). See `platform/CLAUDE.md` plus sub-guides. +- `scripts/` – Build/dev automation. See `scripts/CLAUDE.md`. +- `STYLE_GUIDE.md` – Authoritative style + accessibility + testing reference. +- `README.md`, `config.mk`, `Makefile` – onboarding, env config, and command wiring. + +## Workspace Architecture + +This repository uses npm workspaces: + +- **channels** (`channels/`): Main Mattermost web app containing all UI components, Redux logic, and application code +- **@mattermost/types** (`platform/types/`): TypeScript type definitions +- **@mattermost/client** (`platform/client/`): REST and WebSocket client for the Mattermost API +- **@mattermost/components** (`platform/components/`): Shared React components +- **@mattermost/eslint-plugin** (`platform/eslint-plugin/`): Custom ESLint rules + +### Importing Packages + +Always import packages using their full name, never relative paths: +```typescript +// Correct +import {Client4} from '@mattermost/client'; +import {UserProfile} from '@mattermost/types/users'; +import {getUser} from 'mattermost-redux/selectors/entities/users'; + +// Incorrect +import Client4 from '../platform/client/src/client4.ts'; +``` + +## Key Dependencies + +- **React 18.2**: Main UI framework +- **Redux 5.0**: State management +- **React Router 5.3**: Client-side routing +- **React Intl**: Internationalization +- **Floating UI**: Tooltips and popovers (prefer `WithTooltip` component) +- **@mattermost/compass-icons**: Icon library (prefer over font-awesome) +- **Monaco Editor**: Code editor integration +- **Styled Components**: Limited use (for MUI and some legacy components) + +## Important Configuration Files + +- `channels/webpack.config.js`: Webpack configuration with module federation +- `channels/jest.config.js`: Jest test configuration +- `channels/tsconfig.json`: TypeScript configuration with workspace references +- `channels/.eslintrc.json`: ESLint configuration + +## Cross-Cutting Standards & Common Gotchas + +- **Functional Components**: Prefer functional React components with hooks; memoize expensive logic. +- **Data Access**: Client4/WebSocket access happens via Redux actions only—never directly from components. +- **Internationalization**: All UI strings must be translatable via React Intl. Use `FormattedMessage` unless a raw string is required. +- **Styling**: Uses SCSS + CSS variables with BEM naming; avoid `!important` unless migrating legacy code. +- **Testing**: RTL + `userEvent` for tests; no snapshots. Use helpers under `channels/src/tests/`. +- **Accessibility**: Follow guidance in `STYLE_GUIDE.md` (semantic elements, keyboard support, focus management). +- **Platform Packages**: Rebuild automatically on `npm install`; re-run if types appear stale. +- **Adding Dependencies**: Always add dependencies with `npm add --workspace=channels` (or the relevant workspace). +- **Redux State Split**: `state.entities.*` (server data via mattermost-redux) vs `state.views.*` (UI/persisted). Store new server entities in mattermost-redux first. +- **Client4 Returns**: Methods return `{response, headers, data}` – unwrap accordingly in actions. + +## Nested CLAUDE Files + +- Channels workspace: `channels/CLAUDE.md`, `channels/src/CLAUDE.md`. +- Channels source subfolders: `components/`, `actions/`, `selectors/`, `reducers/`, `store/`, `sass/`, `i18n/`, `tests/`, `utils/`, `types/`, `plugins/`, `packages/mattermost-redux/`. +- Platform packages: `platform/CLAUDE.md`, plus `platform/client/`, `platform/components/`, `platform/types/`. +- Tooling: `scripts/CLAUDE.md`. + +Use these nested guides for focused, actionable instructions when working within each directory. diff --git a/webapp/channels/CLAUDE.OPTIONAL.md b/webapp/channels/CLAUDE.OPTIONAL.md new file mode 100644 index 00000000000..037fc9d9ee6 --- /dev/null +++ b/webapp/channels/CLAUDE.OPTIONAL.md @@ -0,0 +1,73 @@ +# CLAUDE: `webapp/channels/` + +## Purpose +- Main Mattermost web client workspace; almost every UI or Redux change flows through this package. +- Runs as an npm workspace – use `--workspace=channels` when installing deps or running scripts. +- Builds a federated bundle consumed by the server and plugins. + +## Local Commands +- `npm run dev-server --workspace=channels` – hot-reload development server. +- `npm run build --workspace=channels` – production bundle (invokes webpack config in this folder). +- `npm run test --workspace=channels` / `npm run test:watch --workspace=channels`. +- `npm run check --workspace=channels` and `npm run fix --workspace=channels` for lint/style fixes. + +## Directory Structure (src/) + +``` +src/ +├── components/ # React components organized by feature (300+ subdirectories) +├── actions/ # Redux action creators (sync and async thunks) +├── selectors/ # Redux selectors for deriving state +├── reducers/ # Redux reducers for state management +├── utils/ # Utility functions and helpers +├── tests/ # Test utilities and helpers +├── i18n/ # Internationalization files +├── sass/ # Global SCSS styles and theme variables +├── types/ # TypeScript type definitions specific to the web app +├── store/ # Redux store configuration with redux-persist +├── plugins/ # Plugin integration points +├── packages/ +│ └── mattermost-redux/ # Core Redux layer (actions, reducers, selectors) +├── entry.tsx # Application entry point +└── root.tsx # Root React component +``` + +## State Management +- **Redux + Redux Thunk**: Central state management using Redux with thunk middleware for async actions. +- **Redux Persist**: State persistence using localForage with cross-tab synchronization. +- **Mattermost Redux**: Core Redux logic (`state.entities.*` for server data). +- **State Views**: `state.views.*` for UI state (modals, sidebars, preferences). +- **Client4**: Singleton HTTP client for API requests. Should only be used in Redux actions. + +## Key Files +- `package.json` – workspace-specific scripts, env vars, and browserlist targets. +- `webpack.config.js` – module federation + alias map; update remotes or exposes here only when necessary. +- `jest.config.js` – test roots, transformers, moduleNameMapper for workspace aliases. +- `tsconfig.json` – project references for `src`, `tests`, and embedded packages. + +## TypeScript Configuration +- **Strict Mode**: TypeScript strict mode enabled with `strictNullChecks` +- **Path Aliases**: Configured for `@mattermost/*` packages and `mattermost-redux/*` +- **Composite Projects**: Uses TypeScript project references for workspace packages +- **No Any**: Avoid `any` types; legacy code may have them but new code should be typed + +## Module Federation Notes +- Use `channels/src/module_registry.ts` to register async chunks; never import plugin remotes synchronously. +- Exposed modules must stay backward compatible; document any break in `webapp/README.md`. +- When adding a new remote, coordinate with server config (see `webpack.config.js` → `remotes`). +- Prefer wrapping plugin surfaces in adapter components so that federated boundaries remain stable. + +## Dependencies & UI Stack +- React 18, Redux 5, React Router 5, React Intl, Floating UI, Compass Icons, Monaco. +- Follow `webapp/STYLE_GUIDE.md → Dependencies & Packages` before introducing new libs. +- `@mattermost/types`, `@mattermost/client`, and `platform/components` are first-party packages; import via full package names, not deep relative paths. + +## Common Gotchas +- Postinstall builds platform packages—if TypeScript types feel stale, re-run `npm install` at repo root. +- Use `npm add --workspace=channels` to avoid polluting other workspaces. +- Environment-specific overrides live in `config/` on the server side; do not hard-code URLs or feature flags here. +- Webpack aliases mirror tsconfig paths; keep both in sync when adding a new alias. + +## References +- `webapp/STYLE_GUIDE.md → Automated Style Checking`, `Dependencies & Packages`. +- `webapp/README.md` for high-level architecture and release info. diff --git a/webapp/channels/src/CLAUDE.OPTIONAL.md b/webapp/channels/src/CLAUDE.OPTIONAL.md new file mode 100644 index 00000000000..bac763977d3 --- /dev/null +++ b/webapp/channels/src/CLAUDE.OPTIONAL.md @@ -0,0 +1,36 @@ +# CLAUDE: `channels/src/` + +## Purpose +- React + Redux source for the Channels app. Everything rendered in the browser lives here. +- Split by concern: UI (`components`, `sass`), data (`actions`, `reducers`, `selectors`, `store`), utilities, and feature-specific packages. + +## Directory Map +- `components/` – feature folders for UI (see `components/CLAUDE.md`). +- `actions/`, `reducers/`, `selectors/`, `store/` – Redux stack (each has its own CLAUDE). +- `sass/` – theme variables and global styles. +- `i18n/` – locale JSON plus helpers. +- `utils/`, `types/` – shared helpers + local type definitions. +- `packages/mattermost-redux/` – embedded redux package mirroring the standalone repo. + +## Layering Rules +- Components never call `Client4` directly; async work flows through `actions` → `mattermost-redux` → API packages. +- Shared state comes from `mattermost-redux/state.entities.*`; UI/persisted state belongs in `state.views.*`. +- Prefer hooks (`useSelector`, `useDispatch`, custom hooks) over legacy HOCs. +- Keep cross-layer imports stable: `components` may import `selectors`, `utils`, `types`, but not `reducers` or `store`. + +## State Management Primer +- Redux store configured in `store/index.ts`; persistence handled via redux-persist + localForage. +- Selector factories (`makeGet...`) should be memoized per component instance. +- Use `mattermost-redux` for server-backed data; add new entity fields there first, then expose selectors into this workspace. + +## How to Navigate +- Start from route entry (`root.tsx` and `root.html`) to understand bootstrapping and async chunk loading. +- `module_registry.ts` registers dynamically loaded views; ensure new routes/components are wrapped with `makeAsyncComponent` where appropriate. +- Before adding a new folder, check for an existing feature area under `components` or `utils`. + +## References +- `webapp/STYLE_GUIDE.md → React Component Structure`, `Redux & Data Fetching`. +- Example: `root.tsx` (bootstrapping), `module_registry.ts` (async component wiring). + + + diff --git a/webapp/channels/src/actions/CLAUDE.OPTIONAL.md b/webapp/channels/src/actions/CLAUDE.OPTIONAL.md new file mode 100644 index 00000000000..0bfa19f27ad --- /dev/null +++ b/webapp/channels/src/actions/CLAUDE.OPTIONAL.md @@ -0,0 +1,76 @@ +# CLAUDE: `actions/` + +## Purpose +- Hosts Redux action creators (sync + thunk) for UI behaviors and server calls specific to the Channels webapp. +- Bridges components to `mattermost-redux` and `@mattermost/client`. + +## Directory Structure + +``` +actions/ +├── *.ts # Domain-specific actions (channel_actions.ts, post_actions.ts, etc.) +└── views/ # UI-specific actions (modals, sidebars, etc.) +``` + +## Action Patterns + +### Async Thunks + +All async thunks must return `{data: ...}` on success or `{error: ...}` on failure. + +```typescript +export function fetchSomething(id: string): ActionFuncAsync { + return async (dispatch, getState) => { + try { + const data = await Client4.getSomething(id); + dispatch({type: ActionTypes.RECEIVED_SOMETHING, data}); + return {data}; + } catch (error) { + forceLogoutIfNecessary(error, dispatch, getState); + dispatch(logError(error)); + return {error}; + } + }; +} +``` + +### Using bindClientFunc + +For simple API calls, use `bindClientFunc` helper for standard error handling: + +```typescript +export function fetchUser(userId: string): ActionFuncAsync { + return bindClientFunc({ + clientFunc: Client4.getUser, + params: [userId], + onSuccess: ActionTypes.RECEIVED_USER, + }); +} +``` + +## Conventions & Best Practices +- **Response Structure**: Async actions return `{data}` on success or `{error}` on failure (see `webapp/STYLE_GUIDE.md → Redux & Data Fetching`). +- **Actions Only**: Call `Client4` only inside actions; components should dispatch actions, never hit APIs directly. +- **Helpers**: Extract reusable async logic into helpers (`hooks.ts`, `apps.ts`) rather than duplicating inside multiple actions. +- **Entity Data**: When adding new entity data, first wire it through `channels/src/packages/mattermost-redux`, then consume selectors here. + +## Error & Logging Requirements +- Catch errors to call `forceLogoutIfNecessary(error)` and dispatch `logError`. +- Use telemetry wrappers (`trackEvent`, `perf`) when adding analytics inside thunks. +- Always dispatch optimistic UI updates with corresponding failure rollback where user experience demands it. + +## Batching Network Requests +- Use bulk API endpoints when available. +- Use `DelayedDataLoader` for batching multiple calls. +- Fetch data from parent components, not individual list items. + +## views/ Subdirectory +UI state actions that don't involve server data (modals, sidebars, view state) dispatch to `state.views.*` reducers rather than `state.entities.*`. + +## Testing +- Favor RTL-style async action tests with mocked store where possible (`channel_actions.test.ts`). +- Use `nock` or request-mocking utilities in `mattermost-redux` tests for complex flows. + +## References +- `channel_actions.ts`, `global_actions.tsx` – canonical patterns for async thunks. +- `mattermost-redux/src/actions/*` – shared actions; import instead of duplicating server logic. diff --git a/webapp/channels/src/components/CLAUDE.OPTIONAL.md b/webapp/channels/src/components/CLAUDE.OPTIONAL.md new file mode 100644 index 00000000000..ce4d4b9f6a8 --- /dev/null +++ b/webapp/channels/src/components/CLAUDE.OPTIONAL.md @@ -0,0 +1,85 @@ +# CLAUDE: `components/` + +## Purpose +- Folder-by-feature organization for every UI surface. +- Each subfolder should include component, SCSS, tests, and local helpers when needed. + +## File Structure + +Each component directory should contain: +``` +my_component/ +├── index.ts # Re-exports +├── my_component.tsx # Component implementation +├── my_component.scss # Co-located styles (imported in component) +└── my_component.test.tsx +``` + +## Authoring Pattern +- **Functional Components**: Use hooks (`useSelector`, `useDispatch`, `useCallback`, `useMemo`). See `webapp/STYLE_GUIDE.md → React Component Structure`. +- **Small Files**: Split heavy logic into hooks (`useX.ts`) or child components. +- **Memoization**: Use `React.memo` for components with heavy render logic. +- **Code Splitting**: Lazy-load bulky routes using `makeAsyncComponent`: + +```typescript +const HeavyComponent = makeAsyncComponent( + () => import('./heavy_component'), +); +``` + +## Styling & Theming + +- **Co-location**: Put styles in SCSS file next to the component (`import './my_component.scss'`). +- **Root Class**: Match component name in PascalCase (e.g., `.MyComponent`). +- **Child Elements**: Use BEM-style suffix (e.g., `.MyComponent__title`). +- **Theme Variables**: Always use `var(--variable-name)` for colors from `sass/base/_css_variables.scss`. +- **No !important**: Use proper specificity and naming. +- **Transparency**: Use `rgba(var(--color-rgb), 0.5)` for opacity. + +```scss +// my_component.scss +.MyComponent { + color: var(--center-channel-color); + + &__title { + font-weight: 600; + } + + &.compact { + padding: 4px; + } +} +``` + +## Accessibility + +- **Semantic HTML**: Use `