# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Build and Development Commands

```bash
pnpm i                         # Install dependencies (sets up Husky hooks)
pnpm dev                       # Run all packages in watch mode (UI at http://localhost:8181/clinic/)
pnpm dev:mock                  # Dev with MSW API mocking (REACT_APP_MSW=true)
pnpm build                     # Build all packages

# Web package specific (from root)
pnpm --filter @clinic/web lint        # ESLint check
pnpm --filter @clinic/web type-check  # TypeScript check
pnpm --filter @clinic/web fmt         # Prettier format

# API client regeneration
pnpm gen:api                   # Regenerate API clients from OpenAPI specs
```

## Project Architecture

**Monorepo with three packages:**

- `packages/clinic-web/` - Main React UI application (esbuild via gulp)
- `packages/clinic-client/` - TypeScript API client generated from OpenAPI (`swagger/doc.json`)
- `packages/drill-test-client/` - Additional generated API client for drill test service

**Key architectural patterns:**

- **Routing**: React Router v6 with HashRouter. Routes defined in `App.tsx`, page-level routes use descendant routing pattern (`orgs/*`)
- **State management**: Zustand stores in `src/hooks/state.ts` for user, org, and cluster state
- **Data fetching**: SWR for caching/revalidation, react-query also available
- **API layer**: Generated axios clients in `@clinic/client`, wrapped with custom axios instance in `src/api/base.ts` that handles CSRF tokens and auth redirects
- **Styling**: Tailwind CSS + Mantine UI + Ant Design (antd v4). Uses CSS variables and CSS Grid
- **i18n**: react-i18next with YAML translation files in `src/translations/`

**Source structure (`packages/clinic-web/src/`):**

- `pages/` - Route pages, organized by feature (cluster, orgs, event-center, etc.)
- `components/` - Shared UI components
- `hooks/` - Custom hooks including Zustand stores
- `api/` - API wrapper functions using generated clients
- `utils/` - Utilities including `env-config.ts` for all `REACT_APP_*` env vars
- `mocks/` - MSW handlers for API mocking

**Path aliases:**

- `~/` maps to `packages/clinic-web/src/`
- `@clinic/client` and `@drill-test/client` for generated API clients

## Code Style

- 2-space indentation, single quotes, no semicolons (Prettier)
- React components: `PascalCase.tsx`, hooks: `useXxx.ts`
- Import order enforced by ESLint: react → external → internal (@clinic/, @drill-test/, ~/) → relative
- Keep `React` in scope in `.tsx` files (explicit import required)
- Pre-commit hook runs eslint --fix + prettier --write via lint-staged

## Environment Configuration

All `REACT_APP_*` variables centralized in `packages/clinic-web/src/utils/env-config.ts`. Environment files:

- `.env` - base config
- `.env.dev`, `.env.staging`, `.env.prod` - environment-specific
- `.env.local` - local overrides (not committed)

## API Client Generation

```bash
# Update spec and regenerate (default)
pnpm gen:api

# Skip spec update (use existing doc.json)
UPDATE_SPEC=false pnpm gen:api

# Use staging spec instead of dev
DEPLOY_ENV=staging pnpm gen:api
```

Generated clients use OpenAPI Generator with typescript-axios template.

## Generated Assets

`packages/slow-log-explorer` builds static assets into `packages/clinic-web/public/slow-log-explorer-app/` through Vite. `pnpm build` and CI regenerate this directory before the web app build, and Docker packaging consumes the rebuilt `packages/clinic-web/dist`.

Do not commit generated files under `packages/clinic-web/public/slow-log-explorer-app/`. If they show up in a merge or release conflict, remove the tracked generated files and rely on the build output.

## Release Process

Branch model:

- `main` is the code trunk.
- `release` is the release trunk. It contains the released code plus release-only files such as `docker/release-version` and `changelog/`.

Normal code merge and release flow:

1. Update `main`, branch from `main`, and make the code change.
2. Commit and push the branch, then open a PR targeting `main`.
3. After the PR merges, the code is on the main trunk.
4. When a release is needed, update both `main` and `release`, check out `release`, and create a `release-YYYYMMDD.XX` branch. The branch suffix must match the version written to `docker/release-version`.
5. Merge `main` into the release branch. If source-code conflicts occur, resolve them with the `main` implementation unless the conflict is in release-only metadata.
6. Update `docker/release-version`:
   - Keep the first line as exactly one comment line.
   - Put the version on the next line.
   - Use `YYYYMMDD.XX`, for example `20260623.01`, where `XX` is the release sequence for that day.
7. Update `changelog/`.
8. Commit and push the release branch, then open a PR targeting `release`.

Hotfix flow:

1. Check out `main`, update it, and branch from `main` for the hotfix.
2. Make the fix.
3. Commit and push the branch, then open a PR targeting `main`.
4. Prepare the release hotfix PR:
   - Check out `release` and update it.
   - Create a hotfix release branch.
   - Cherry-pick the just-merged hotfix PR changes.
   - Update `docker/release-version` and `changelog/`.
5. Commit and push the hotfix release branch, then open a PR targeting `release`.
