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 ## Routing - All routes are lazy loaded (`loadComponent` / `loadChildren`), including feature-internal ones - All routes render as a plain client-side SPA (`RenderMode.Client` in `app.routes.server.ts`). Do NOT use SSR or prerender by default; enable them only for specific routes the user explicitly asks for ## Project Structure - Organize code by feature, not by file type: `src/app//` (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 (`.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/`, `fix/`, `release/` - Do NOT create branches on your own: the user creates a branch (named as above) when a task is large (a feature, many related changes). Otherwise work in the current branch - Small point corrections (config tweaks, adding a dependency, minor fixes) need no separate branch: they go straight to the current branch, usually `main`, as a normal Conventional Commit - 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 the current 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