Add optional Claude.md orchestration for Webapp folder (#34668)
Some checks are pending
API / build (push) Waiting to run
Server CI / Compute Go Version (push) Waiting to run
Server CI / Check mocks (push) Blocked by required conditions
Server CI / Check go mod tidy (push) Blocked by required conditions
Server CI / check-style (push) Blocked by required conditions
Server CI / Check serialization methods for hot structs (push) Blocked by required conditions
Server CI / Vet API (push) Blocked by required conditions
Server CI / Check migration files (push) Blocked by required conditions
Server CI / Generate email templates (push) Blocked by required conditions
Server CI / Check store layers (push) Blocked by required conditions
Server CI / Check mmctl docs (push) Blocked by required conditions
Server CI / Postgres with binary parameters (push) Blocked by required conditions
Server CI / Postgres (push) Blocked by required conditions
Server CI / Postgres (FIPS) (push) Blocked by required conditions
Server CI / Generate Test Coverage (push) Blocked by required conditions
Server CI / Run mmctl tests (push) Blocked by required conditions
Server CI / Run mmctl tests (FIPS) (push) Blocked by required conditions
Server CI / Build mattermost server app (push) Blocked by required conditions
Web App CI / check-lint (push) Waiting to run
Web App CI / check-i18n (push) Blocked by required conditions
Web App CI / check-types (push) Blocked by required conditions
Web App CI / test (platform) (push) Blocked by required conditions
Web App CI / test (mattermost-redux) (push) Blocked by required conditions
Web App CI / test (channels shard 1/4) (push) Blocked by required conditions
Web App CI / test (channels shard 2/4) (push) Blocked by required conditions
Web App CI / test (channels shard 3/4) (push) Blocked by required conditions
Web App CI / test (channels shard 4/4) (push) Blocked by required conditions
Web App CI / upload-coverage (push) Blocked by required conditions
Web App CI / build (push) Blocked by required conditions

* 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
This commit is contained in:
Nick Misasi 2026-01-14 13:04:20 -05:00 committed by GitHub
parent cc2b47bc9b
commit 0885f56010
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 987 additions and 1 deletions

2
.gitignore vendored
View file

@ -161,5 +161,5 @@ docker-compose.override.yaml
.env .env
**/CLAUDE.local.md **/CLAUDE.local.md
CLAUDE.md **/CLAUDE.md
.cursorrules .cursorrules

16
enable-claude-docs.sh Executable file
View file

@ -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."

98
webapp/CLAUDE.OPTIONAL.md Normal file
View file

@ -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 <pkg> --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.

View file

@ -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 <pkg> --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.

View file

@ -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).

View file

@ -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.

View file

@ -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 `<button>`, `<input>`, etc. over `<div>` with roles.
- **Keyboard Support**: All interactive elements must be keyboard accessible.
- **Helpers**: Reuse primitives like `GenericModal`, `Menu`, `WithTooltip`, `A11yController` helpers.
- **Focus**: Use `a11y--focused` class for keyboard focus indicators.
- **Images**: Alt text required for information images. Empty `alt=""` for decorative.
## Internationalization
- All UI text must use React Intl.
- Prefer `<FormattedMessage>` over `useIntl()` hook when possible.
- **Rich Text**: Use React Intl's rich text support (e.g., `values={{b: (chunks) => <b>{chunks}</b>}}`) instead of splitting strings.
```typescript
// Preferred
<FormattedMessage id="component.title" defaultMessage="Title" />
// When string is needed for props
const intl = useIntl();
<input placeholder={intl.formatMessage({id: 'input.placeholder', defaultMessage: 'Search...'})} />
```
## Testing Expectations
- Add/extend RTL tests alongside the component (`*.test.tsx`). See `../tests/react_testing_utils.tsx` for helpers.
- Prefer `userEvent` and accessible queries (`getByRole`) over implementation-specific selectors.
- Avoid snapshots; assert visible behavior instead.
## Useful Examples
- `channel_view/channel_view.tsx` full-page component structure with co-located SCSS.
- `post_view/post_list_virtualized/post_list_virtualized.tsx` virtualization + hooks pattern.
- `widgets/menu` components accessible menu behaviors.

View file

@ -0,0 +1,26 @@
# CLAUDE: `i18n/`
## Purpose
- Houses locale JSON files and helpers for React Intl integration.
- Ensures every user-facing string in the Channels app is translatable.
## Workflow
- Add new message IDs to `en.json` ONLY.
- Reference strings via `FormattedMessage`, `intl.formatMessage`, or `t('id')` helpers—never hard-code text.
- After editing locale files, run `npm run extract-intl --workspace=channels` (or the appropriate script) if available to sync translations.
- Keep message IDs stable; renaming requires migration guidance for localization teams.
## Guidelines
- Follow `webapp/STYLE_GUIDE.md → Internationalization`.
- Prefer `FormattedMessage` components that wrap child markup for rich text instead of concatenating strings.
- When adding intl utilities outside React, return `MessageDescriptor` objects where possible.
- Avoid `localizeMessage`; use modern helpers.
## Helper Files
- `utils/react_intl.ts` shared helper functions for formatting and caching.
- `tests/react_testing_utils.tsx` demonstrates how to provide Intl context for tests.
## References
- Example translations: `en.json`, `es.json`.
- React Intl docs: <https://formatjs.io/docs/react-intl/>.

View file

@ -0,0 +1,64 @@
# CLAUDE: `packages/mattermost-redux/`
## Purpose
- Embedded copy of the `mattermost-redux` package for local development.
- Owns canonical Redux entities, actions, selectors, and request helpers shared across products (Channels, Boards, Playbooks).
- Manages server-sourced data (`state.entities.*`) and API actions.
## Directory Structure (src/)
```
src/
├── actions/ # API actions (channels.ts, users.ts, posts.ts, etc.)
├── action_types/ # Action type constants
├── reducers/
│ ├── entities/ # Entity reducers (one per domain)
│ └── requests/ # Request status tracking
├── selectors/
│ ├── entities/ # Entity selectors
│ └── create_selector/ # Memoized selector helper
├── constants/ # App constants
├── store/ # Store configuration helpers
├── utils/ # Utility functions
└── client/ # Client4 re-export
```
## State Organization
All state managed here lives under `state.entities` (users, channels, posts, teams, etc.).
- **state.entities**: Server-sourced data.
- **state.requests**: Network request tracking.
- **state.errors**: Global errors.
UI-specific state lives outside this package in `state.views`.
## Import Convention
Import from mattermost-redux using the package alias:
```typescript
// Actions
import {getUser} from 'mattermost-redux/actions/users';
// Selectors
import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
// Constants
import {General} from 'mattermost-redux/constants';
// Types come from @mattermost/types
import {UserProfile} from '@mattermost/types/users';
```
## When to Edit
- Add/modify server-sourced entities (`state.entities.*`), request status tracking, or shared selectors.
- Introduce new Client4 endpoints (paired with `platform/client`) or action helpers.
- Avoid webapp-specific logic; keep files reusable across products.
## Adding New Entities
1. Create action types in `action_types/`
2. Create reducer in `reducers/entities/`
3. Register reducer in `reducers/entities/index.ts`
4. Create selectors in `selectors/entities/`
5. Create actions in `actions/`
## Conventions
- All async actions return `{data}` or `{error}` objects; keep request statuses updated via `RequestTypes`.
- When adding endpoints, update `client/index.ts`, Types, and relevant action/reducer files.
- Maintain TypeScript strictness; add tests under `__tests__` where behaviors are complex.
- Coordinate API contracts with server changes; document required server versions in commit/PR descriptions.

View file

@ -0,0 +1,29 @@
# CLAUDE: `plugins/`
## Purpose
- Handles plugin registration, exported surfaces, and compatibility glue between the Channels app and plugin ecosystem.
- Provides TypeScript helpers and UI entry points for third-party integrations.
## Key Files
- `index.ts` plugin entry, initializes registry, exposes activators.
- `registry.ts` core API for plugins to register components, reducers, actions, webhooks.
- `products.ts` / `actions.ts` plugin-aware UX helpers.
- `docs.json` describes exposed plugin APIs; update when changing interfaces.
## Guidelines
- Follow `webapp/STYLE_GUIDE.md → Plugin Development`.
- Keep exported surfaces stable; deprecate with clear comments and update docs.
- Limit new dependencies—plugins should consume primitives already available in Channels or `platform/components`.
- Test plugin UI surfaces via `plugins/test/` and integration suites; ensure fallbacks when plugins misbehave.
## Security & Stability
- Validate plugin-supplied components/props before rendering to avoid breaking the host app.
- Wrap remote components in error boundaries when possible.
- Document required props and shapes in `plugins/user_settings.ts` or dedicated type files.
## References
- `registry.ts` for API expectations.
- Sample plugin UI: `channel_header_plug/`, `rhs_plugin/`, `textbox/`.

View file

@ -0,0 +1,28 @@
# CLAUDE: `reducers/`
## Purpose
- Define how Redux state changes in response to actions for the Channels webapp.
- Split between `state.entities.*` (server data via mattermost-redux) and `state.views.*` (webapp UI + persisted state).
## Structure
- Root reducer composition lives in `reducers/index.ts`.
- Domain reducers belong under `reducers/views/*` for UI state or under `packages/mattermost-redux` for server entities.
- Keep files focused: one reducer per domain with clear initial state exports and typed actions.
## Conventions
- Treat state as immutable use spread, `combineReducers`, or helper functions rather than mutating.
- Persistable slices must define their keys in `store/index.ts` persistence config.
- Document any side-effects (e.g., clearing caches when team changes) with inline comments.
## Testing & Validation
- Each reducer should have a companion `*.test.ts` covering happy paths, reset cases, and regression bugs.
- When updating state shape, update TypeScript definitions under `channels/src/types/store/`.
- Keep reducers serialization-safe; avoid storing functions, class instances, or DOM references.
## References
- `reducers/views/channel_sidebar.ts` example of complex UI reducer.
- `reducers/index.ts` wiring pattern for new reducers.
- `webapp/STYLE_GUIDE.md → Organizing Redux State`, `Standards Needing Refinement → Handler Placement`.

View file

@ -0,0 +1,67 @@
# CLAUDE: `sass/`
## Purpose
- Global SCSS for the Channels app: theme tokens, layout primitives, shared mixins.
- Component-specific styles should stay next to their TSX files (see `../components/CLAUDE.md`).
## Directory Structure
```
sass/
├── styles.scss # Main entry point (imports all modules)
├── base/
│ ├── _css_variables.scss # Theme CSS variables (colors, elevations, radii)
│ ├── _structure.scss # Base structural styles
│ └── _typography.scss # Typography defaults
├── components/ # Global component styles (legacy)
├── layout/ # Layout styles (headers, sidebars, content)
├── responsive/ # Responsive breakpoint styles
├── routes/ # Route-specific styles
├── utils/
│ ├── _mixins.scss # Reusable mixins
│ ├── _functions.scss # SCSS functions
│ ├── _variables.scss # SCSS variables (non-CSS)
│ └── _animations.scss # Animation definitions
└── widgets/ # Widget styles
```
## Theme Variables
All theme colors are defined in `base/_css_variables.scss`. Always use CSS variables for colors:
```scss
// GOOD
.MyComponent {
color: var(--center-channel-color);
background: var(--center-channel-bg);
border: var(--border-default);
}
```
### Key Variable Categories
- **Colors**: `--center-channel-color`, `--link-color`, `--button-bg`.
- **RGB variants**: `--center-channel-color-rgb` (for rgba transparency).
- **Elevation**: `--elevation-1` through `--elevation-6`.
- **Radius**: `--radius-xs` through `--radius-full`.
- **Borders**: `--border-default`, `--border-light`, `--border-dark`.
## Responsive Patterns
Use mixins from `utils/_mixins.scss` for responsive styles; do not hard-code media queries.
```scss
@import 'utils/mixins';
.MyComponent {
padding: 16px;
@include tablet { padding: 12px; }
@include mobile { padding: 8px; }
}
```
## Styling Rules
- **Naming**: Use PascalCase root class matching component name. Use BEM for children (`.ComponentName__element`) and modifiers (`&.modifier`).
- **Specificity**: Avoid `!important`; favor specificity via nested classes or utility mixins.
- **Units**: Prefer `px` for sizing unless inheriting from existing `rem` usage; keep consistent within a file.
## Cleanup Targets
- Replace hard-coded values with shared tokens.
- Migrate legacy element selectors to component-scoped classes when files are touched.

View file

@ -0,0 +1,63 @@
# CLAUDE: `selectors/`
## Purpose
- Derive memoized data from Redux state for use in components, hooks, and actions.
- Keep state computations centralized to avoid duplication and unnecessary renders.
## Directory Structure
```
selectors/
├── *.ts # Domain-specific selectors (drafts.ts, rhs.ts, etc.)
└── views/ # UI state selectors matching views/ reducers
```
## Memoization Requirements
### When to Memoize
Selectors that return **new objects or arrays** must use `createSelector` from reselect:
```typescript
import {createSelector} from 'mattermost-redux/selectors/create_selector';
// GOOD - memoized
export const getVisibleChannels = createSelector(
'getVisibleChannels',
(state: GlobalState) => state.entities.channels.channels,
(channels) => Object.values(channels).filter(c => c.visible),
);
```
### Selector Factories
When a selector takes arguments, use a `makeGet...` factory for per-instance memoization:
```typescript
// Factory creates a new memoized selector instance
export function makeGetChannel() {
return createSelector(
'getChannel',
(state: GlobalState) => state.entities.channels.channels,
(state: GlobalState, channelId: string) => channelId,
(channels, channelId) => channels[channelId],
);
}
```
### Using Factories in Components
```typescript
// Functional component - memoize the selector instance
function ChannelItem({channelId}: Props) {
const getChannel = useMemo(makeGetChannel, []);
const channel = useSelector((state) => getChannel(state, channelId));
}
```
## Usage Rules
- Avoid cross-imports from reducers or store. Selectors should depend only on state shape and other selectors.
- When tapping `mattermost-redux` selectors, re-export or compose them locally for clarity.
- Document any selector that relies on specific state initialization (e.g., persisted drafts) in code comments.
## References
- `webapp/STYLE_GUIDE.md → Redux & Data Fetching → Selectors`.
- `drafts.ts`: Memoized selectors with createSelector.
- `views/modals.ts`: Modal state selectors.

View file

@ -0,0 +1,27 @@
# CLAUDE: `store/`
## Purpose
- Configures the Redux store, middleware stack, and persistence for the Channels webapp.
- Entry point for wiring reducers, enhancers, telemetry, and devtools.
## Key Files
- `index.ts` store factory, middleware registration, persistence config.
- `index.test.ts` regression tests for middleware order and persistence.
## Conventions
- Middleware order matters: diagnostics/logging first, async (thunk) middle, routing last.
- Persistence uses `redux-persist` + `localForage`. Keep whitelist/blacklist in sync with reducer ownership.
- Avoid adding new global listeners in the store; prefer feature-specific middleware or hooks.
- When adding middleware, document why a global solution is needed versus feature-level listeners.
## Cross-Workspace Rules
- Shared entities live in `mattermost-redux`. Only include webapp-specific reducers here.
- Do not instantiate `Client4` or other singletons in the store; inject via actions/middleware.
- Keep store typing up to date via `channels/src/types/store/index.ts` to ensure selectors have accurate types.
## References
- `webapp/STYLE_GUIDE.md → Redux & Data Fetching` (state organization, persistence guidance).
- Example middleware: `websocket_actions.jsx` wiring, `plugins` middleware from `channels/src/plugins`.

View file

@ -0,0 +1,46 @@
# CLAUDE: `tests/`
## Purpose
- Centralizes shared test utilities, mocks, and sample data for the Channels webapp.
- Provides helpers so component and Redux tests stay concise and user-focused.
## Key Files
- `react_testing_utils.tsx`: Primary test utilities (exports `renderWithContext`, providers, custom matchers).
- `test_store.tsx`: Mock Redux store for testing.
- `setup_jest.ts`: Global Jest config and mocks.
## Testing Guidelines (RTL)
- **User-Centric**: Test interactions and visible behavior, not implementation.
- **No Snapshots**: Write explicit assertions with `expect(...).toBeVisible()`.
- **Accessible Selectors**: Prefer `getByRole` > `getByText` > `getByLabelText` > `getByTestId`.
- **userEvent**: Use `userEvent` over `fireEvent`, always await.
## renderWithContext
Always use `renderWithContext` for components that need Redux, Router, or I18n context:
```typescript
import {renderWithContext, screen, userEvent} from 'tests/react_testing_utils';
describe('MyComponent', () => {
it('renders correctly', async () => {
const {container} = renderWithContext(
<MyComponent prop="value" />,
{
entities: { users: { currentUserId: 'user1' } }, // Partial initial state
},
);
expect(screen.getByRole('button')).toBeVisible();
});
});
```
## Adding Helpers
- Place reusable mocks under `helpers/` (e.g., `intl-test-helper.tsx`, `match_media.mock.ts`).
- Document custom utilities with inline comments.
- If a helper becomes product-agnostic, consider moving it to `platform/components/testUtils.tsx`.
## Available Mocks
- `helpers/match_media.mock.ts`: matchMedia mock
- `helpers/localstorage.tsx`: localStorage mock
- `react-intl_mock.ts`: React Intl mock
- `react-router-dom_mock.ts`: React Router mock

View file

@ -0,0 +1,28 @@
# CLAUDE: `types/`
## Purpose
- Local TypeScript declarations shared across the Channels app (store shapes, plugin types, third-party d.ts shims).
- Complements `platform/types` by covering webapp-only constructs.
## Structure
- `store/` canonical Redux store typings; update when reducers change.
- `plugins/`, `apps.ts`, `actions.ts` domain-specific interfaces.
- `external/` ambient declarations for libraries without published types.
## Guidelines
- Keep files small and discoverable; prefer feature-specific files (`cloud/sku.ts`) instead of dumping into `global.d.ts`.
- Avoid `any`; if unavoidable, annotate why and track TODO for future refinement.
- Align naming with server and platform types to prevent duplication (e.g., reuse `UserProfile` from `@mattermost/types`).
- When extending globals (`global.d.ts`), document the reason and include links to usage.
## Coordination
- Shared type changes should originate in `platform/types`; after publishing, update imports here.
- Update `tsconfig.json` references and ESLint overrides if new directories are added.
- Regenerate API/Redux types where applicable when adding new store slices.
## References
- `store/index.ts` consumes these definitions for typed selectors.
- `webapp/STYLE_GUIDE.md → TypeScript`, “Component Prop Typing”.

View file

@ -0,0 +1,41 @@
# CLAUDE: `utils/`
## Purpose
- Shared helper functions, hooks, telemetry utilities, and adapters used across the Channels app.
- Keep business rules out of components/actions by moving reusable logic here.
## Directory Structure
```
utils/
├── *.ts # General utilities
├── markdown/ # Markdown parsing and rendering utilities
├── performance_telemetry/ # Performance monitoring
├── plugins/ # Plugin-related utilities
├── popouts/ # Window popout utilities
└── use_websocket/ # WebSocket React hooks
```
## Key Utilities
### Accessibility
- `a11y_controller.ts`: Enhanced keyboard navigation controller.
- `a11y_utils.ts`: Accessibility helper functions.
### Keyboard Handling
- `keyboard.ts`: Cross-platform keyboard handling.
- Use `isKeyPressed` and `cmdOrCtrlPressed`.
### Text Processing
- `text_formatting.tsx`: Text formatting and sanitization.
- `markdown/`: `renderer.tsx` (custom renderer), `apply_markdown.ts`.
## Guidelines
- **Strong Typing**: Prefer concrete interfaces over `any`. Reference `channels/src/types` or `@mattermost/types`.
- **Purity**: Keep utilities pure when possible. Document side-effects.
- **Accessibility**: Helpers should follow `webapp/STYLE_GUIDE.md → Accessibility`.
- **Organization**: Prefix folders by domain. Avoid sprawling “misc” files.
## Adding New Utilities
1. Create focused, single-purpose utility files.
2. Include tests (`.test.ts`) alongside the utility.
3. Export from the utility file directly.

View file

@ -0,0 +1,45 @@
# CLAUDE: `webapp/platform/`
## Purpose
- Shared packages consumed by every Mattermost web experience (Channels, Boards, Playbooks, plugins).
- Changes here affect multiple products—coordinate across teams before merging.
## Packages
| Package | Directory | Purpose |
|---------|-----------|---------|
| `@mattermost/types` | `types/` | TypeScript type definitions |
| `@mattermost/client` | `client/` | REST and WebSocket API client |
| `@mattermost/components` | `components/` | Shared React components |
| `@mattermost/eslint-plugin` | `eslint-plugin/` | Custom ESLint rules |
## Workspace Basics
- Each subpackage is its own npm workspace with independent `package.json`, tests, and build scripts.
- Run commands with `npm run <script> --workspace=@mattermost/<pkg>` (e.g., `@mattermost/client`).
- Versioning follows the monorepo; publishable artifacts come from CI pipelines.
## Import Convention
Always import using the full package name:
```typescript
// CORRECT
import {Client4} from '@mattermost/client';
// INCORRECT - never use relative paths
import Client4 from '../platform/client/src/client4';
```
## Build Relationship
Platform packages are automatically built on `npm install` via postinstall hook. Build order: `types``client`/`components`.
**Note**: When developing in `channels`, changes in `platform` packages may need a rebuild if not using a watcher that supports them.
## Adding Dependencies
When adding dependencies to platform packages:
```bash
npm add package-name --workspace=@mattermost/client
```
## Expectations
- Follow `webapp/STYLE_GUIDE.md`.
- Maintain 100% TypeScript coverage; no `any`.
- Update downstream consumers when making breaking changes.

View file

@ -0,0 +1,49 @@
# CLAUDE: `platform/client/` (`@mattermost/client`)
## Purpose
- Implements the Client4 HTTP layer and WebSocket client used by all Mattermost web apps and plugins.
- Source of truth for API endpoint definitions and low-level networking helpers.
## Structure
- `src/client4.ts` REST endpoints, auth handling, retries.
- `src/websocket.ts` WebSocket manager for real-time events.
- `src/helpers.ts` / `errors.ts` shared logic for response parsing and error types.
## Client4 Usage
Singleton HTTP client for all Mattermost API requests. Methods return `Promise<ClientResponse<T>>`:
```typescript
interface ClientResponse<T> {
response: Response; // Fetch Response object
headers: Headers; // Response headers
data: T; // Parsed response data
}
```
### Usage Rules
1. **Actions Only**: `Client4` should only be called from Redux actions, never directly in components.
2. **Error Handling**: Always handle errors appropriately.
## Adding New Endpoints
Add new API methods to `client4.ts`. Keep signatures Promise-based.
```typescript
getSomething = (id: string) => {
return this.doFetch<SomethingType>(
`${this.getSomethingRoute(id)}`,
{method: 'get'},
);
};
```
## Error Handling
- Throw `ClientError` (see `errors.ts`) with enough context.
- Include `forceLogoutIfNecessary` logic upstream in calling actions; do not couple that here.
## WebSocket Client
`websocket.ts` provides real-time event handling, connection management, and automatic reconnection. Accessed via `WebSocketClient` wrapper in web app.
## Guidelines
- Follow `webapp/STYLE_GUIDE.md → Networking`.
- Each new server API must be added here first, including TypeScript types and tests.
- Never reference React or browser globals—this package must run in Node.

View file

@ -0,0 +1,30 @@
# CLAUDE: `platform/components/` (`@mattermost/components`)
## Purpose
- Cross-product React components (GenericModal, tour tips, loaders, hooks) shared by Channels, Boards, Playbooks, and plugins.
- Ensures consistent UX, theming, and accessibility across Mattermost surfaces.
## Implementation Guidelines
- Follow `webapp/STYLE_GUIDE.md → React Component Structure`, `Styling & Theming`, `Accessibility`.
- Components must be framework-agnostic: accept data/handlers via props, avoid direct Redux or routing dependencies.
- Keep styles local via SCSS modules or styled components already used in this package; expose classNames for host overrides when necessary.
- Include Storybook/README snippets where helpful (see package README).
## Testing
- All components need RTL tests (`*.test.tsx`) demonstrating accessibility behaviors.
- Provide test utils (`testUtils.tsx`) for consumers who need to mock these components.
## Key Modules
- `generic_modal/` baseline modal with focus trapping and keyboard handling.
- `tour_tip/` coach marks with backdrop management.
- `skeleton_loader/`, `pulsating_dot/` loading indicators.
- `hooks/` shared hooks like `useFocusTrap`.
## Release Notes
- Breaking props or behavior requires updating `platform/components/README.md` and notifying dependent teams.
## References
- `generic_modal/generic_modal.tsx`, `tour_tip/tour_tip.tsx`, `hooks/useFocusTrap.test.tsx`.

View file

@ -0,0 +1,34 @@
# CLAUDE: `platform/types/` (`@mattermost/types`)
## Purpose
- Shared TypeScript definitions for server entities, API payloads, and enums consumed across all Mattermost frontends.
## Structure
Files organized by domain in `src/`:
- `users.ts`, `channels.ts`, `posts.ts`, `teams.ts`, `files.ts`, `preferences.ts`, `config.ts`.
- `utilities.ts` (DeepPartial, etc.).
## Import Convention
Import types using subpath exports:
```typescript
import {UserProfile} from '@mattermost/types/users';
import {Channel} from '@mattermost/types/channels';
```
## Type Conventions
- Use `type` over `interface` for consistency.
- Property names use `snake_case` (matching API responses).
- Timestamps are `number` (milliseconds since epoch).
- IDs are `string`.
- Use `readonly` for immutable properties where appropriate.
## Guidelines
- Maintain compatibility with server REST APIs; align naming and shapes with server structs.
- Export granular types so downstream apps can tree-shake.
- Avoid duplicating types present elsewhere in the monorepo.
## Workflow
- Update types when server contracts change.
- Incrementally add stricter types but ensure backward compatibility.
- Run TypeScript builds/tests for dependent workspaces after modifying shared types.

View file

@ -0,0 +1,25 @@
# CLAUDE: `webapp/scripts/`
## Purpose
- Node-based helpers for building, running, and maintaining the webapp (e.g., dev server orchestration, build pipelines, localization tooling).
- Invoked via `npm`/`make` targets—direct execution should be rare.
## Key Scripts
- `dev-server.mjs` webpack-dev-server bootstrap; shares config with `make dev`.
- `run.mjs`, `build.mjs`, `dist` helpers orchestrate multi-workspace builds and env wiring.
- `gen_lang_imports.mjs` regenerates locale import lists.
- `update-versions.mjs`, `utils.mjs` release automation bits.
## Guidelines
- Scripts should be idempotent and safe to run on CI and macOS/Linux dev machines.
- Prefer ES modules + top-level `await` already used in existing scripts.
- Keep configuration (ports, paths) sourced from `config.mk` or env vars instead of hard-coding.
- Log actionable errors; exit with non-zero codes so CI fails fast.
- When script behavior changes, update associated `Makefile` targets and `webapp/CLAUDE.md` command docs.
## References
- `config.mk`, root `Makefile`, and workspace `package.json` scripts to understand entry points.
- `webapp/STYLE_GUIDE.md → Automated style checking` for how scripts integrate with lint/test tooling.