Files
pchelpmaster/CLAUDE.md
T

99 lines
6.1 KiB
Markdown

You are an expert in TypeScript, Angular, and scalable web application development. You write functional, maintainable, performant, and accessible code following Angular and TypeScript best practices.
## Project Overview
Pchelpcrm is a CRM for handling service requests (orders) of a private service professional: computer help, home repairs, furniture assembly, plumbing, electrical work, etc. The domain is deliberately generic: any "client calls, a job gets done" business fits. Currently used personally by the author, so keep it simple.
Domain entities:
- **User** — the owner of the personal account who works in the CRM (a PocketBase auth record). Everything below belongs to a user and must be isolated per user (API rules).
- **Client** — a customer of the user. A separate entity, not a user.
- **Request** — a service request (order). Belongs to exactly one client; one client can have many requests.
- **Category** — a request category. Dynamic: created and edited by the user, never hardcoded in code or enums.
Auth: PocketBase auth collection, login by email + password.
Stack: Angular (see rules below) + PocketBase (`pocketbase/pb_migrations/` holds the schema) + pnpm. Add other libraries (e.g. a UI component library) only when really needed.
Delivery plan: after the first release the app ships as ONE Docker container (Angular app + PocketBase together, no docker-compose) deployable to a production server. Do not design anything that requires multiple containers.
## TypeScript Best Practices
- Use strict type checking
- Prefer type inference when the type is obvious
- Avoid the `any` type; use `unknown` when type is uncertain
## Angular Best Practices
- Always use standalone components over NgModules
- Must NOT set `standalone: true` inside Angular decorators. It's the default in Angular v20+.
- Do NOT set `changeDetection: ChangeDetectionStrategy.OnPush` explicitly. `OnPush` is the default in Angular v22+.
- Use signals for state management
- Implement lazy loading for feature routes
- Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead
- Use `NgOptimizedImage` for all static images.
- `NgOptimizedImage` does not work for inline base64 images.
## Accessibility Requirements
- It MUST pass all AXE checks.
- It MUST follow all WCAG AA minimums, including focus management, color contrast, and ARIA attributes.
## Components
- Keep components small and focused on a single responsibility
- Use `input()` and `output()` functions instead of decorators
- Use `model()` for two-way bound properties with `[(prop)]` syntax instead of pairing `input()` with `output()`
- Use `computed()` for derived state
- Use `linkedSignal()` for state derived from multiple reactive sources that must stay synchronized
- Prefer inline templates for small components
- Prefer Signal Forms (`@angular/forms/signals`) for new forms. They are stable in Angular v22+ and provide signal-based state, type-safe field access, and schema-based validation
- When not using Signal Forms, prefer Reactive forms instead of Template-driven ones
- Do NOT use `ngClass`, use `class` bindings instead
- Do NOT use `ngStyle`, use `style` bindings instead
- Do NOT import `CommonModule`, import only the directives and pipes the template uses, such as `AsyncPipe` or `DatePipe`
- When using external templates/styles, use paths relative to the component TS file.
## State Management
- Use signals for local component state
- Use `computed()` for derived state
- Keep state transformations pure and predictable
- Do NOT use `mutate` on signals, use `update` or `set` instead
## Templates
- Keep templates simple and avoid complex logic
- Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch`
- Use the async pipe to handle observables
- Do not assume globals like (`new Date()`) are available.
## Services
- Design services around a single responsibility
- Use the `providedIn: 'root'` option for singleton services
- Prefer the `@Service` decorator over `@Injectable({providedIn: 'root'})` for new singleton services (Angular v22+)
- Use the `inject()` function instead of constructor injection
## Project Structure
- Organize code by feature, not by file type: `src/app/<feature>/` (e.g. `src/app/clients/`), not global `components/`, `services/`, `pipes/` folders
- Keep everything a feature needs inside its folder: components, services, models, routes and tests
- One concept per file: one component, directive, pipe or service per file
- Keep the files of one entity together in the same folder with the same base name (`order-list.ts`, `order-list.html`, `order-list.css`, `order-list.spec.ts`)
- Use kebab-case file names. Do NOT add `.component` / `.service` suffixes (matches the existing `app.ts`)
- Put unit tests next to the code they test (`*.spec.ts`)
- Each feature has its own routes file (`<feature>.routes.ts`) and is lazy loaded from `app.routes.ts` via `loadChildren` / `loadComponent`
- Do NOT create `core/` or `shared/` folders upfront; add shared code only when two or more features actually need it
- Features must not import from each other's internals; extract the common part to a shared location instead
## Git Branches
- Follow GitHub Flow: there is NO separate `develop` branch. `main` is the only long-lived branch
- Create every working branch directly from the latest `main`: features, fixes and release preparation alike
- Name branches by purpose in kebab-case: `feat/<short-name>`, `fix/<short-name>`, `release/<version>`
- At the start of each new session / new task, create a new branch from `main` with a name matching the task (`feat/...`, `fix/...`, `release/...`) before making any changes
- Do NOT commit on your own: make a commit only when the user explicitly asks for it, because the user reviews changes before every commit. When asked, commit only to that branch (Conventional Commits)
- Do NOT merge, rebase onto `main`, push, or delete branches: merging and cleaning up branches is done by the user
- There are no pull requests: the user works with a local repository only