Files

298 lines
13 KiB
Markdown

# Angular Code Guidelines
* Use modern Angular patterns and current framework conventions.
* Prefer standalone components, directives and pipes for new code.
* Avoid introducing `NgModule` unless the existing project architecture requires it.
* Keep components small and focused.
* Keep templates simple.
* Move complex logic out of templates.
* Keep business logic out of components where practical.
* Prefer services, facades or dedicated domain logic for non-trivial behavior.
* Avoid god components and god services.
* Keep dependencies explicit.
* Prefer composition over inheritance.
* Avoid unnecessary abstractions.
* Avoid unnecessary wrapper components.
* Follow the existing project architecture unless there is a strong reason to change it.
## Components
* Use `ChangeDetectionStrategy.OnPush` unless there is a concrete reason not to.
* Prefer signal-based state for local component state.
* Prefer `computed` for derived state.
* Prefer `effect` only for actual side effects.
* Do not use `effect` as a replacement for normal data flow.
* Keep component state minimal.
* Avoid duplicating derived state.
* Prefer immutable state updates.
* Avoid direct mutation of shared state.
* Keep inputs and outputs strongly typed.
* Prefer signal-based inputs and outputs when consistent with the project.
* Avoid unnecessary two-way binding.
* Avoid unnecessary component-to-component coupling.
* Prefer explicit data flow from parent to child and explicit events upward.
* Do not expose internal component state unnecessarily.
* Use lifecycle hooks only when required.
* Avoid complex initialization logic inside constructors.
## Templates
* Keep expressions short and readable.
* Do not execute expensive methods from templates.
* Avoid function calls in templates when their result can be derived or cached.
* Avoid complex conditions directly in markup.
* Prefer derived state in TypeScript over repeated template expressions.
* Use Angular control flow syntax such as `@if`, `@for` and `@switch` for new code.
* Always provide stable tracking for repeated collections.
* Avoid deeply nested template structures.
* Split large templates into focused components when it improves maintainability.
* Avoid unnecessary DOM elements.
* Use semantic HTML.
* Prefer native HTML behavior before custom implementations.
* Keep accessibility in mind when choosing elements and interactions.
## Signals and State
* Prefer signals for local and synchronous reactive state.
* Prefer `computed` for derived values.
* Keep signals private when external mutation is not intended.
* Expose readonly state where practical.
* Avoid storing values that can be derived from existing state.
* Avoid circular signal dependencies.
* Avoid side effects inside `computed`.
* Keep effects small and deterministic.
* Clean up resources created by effects.
* Do not use global state unless multiple unrelated parts of the application genuinely need it.
* Do not introduce a state-management library without a clear requirement.
## RxJS
* Use RxJS for asynchronous streams, events and complex reactive flows.
* Do not use RxJS when simple synchronous signals are sufficient.
* Prefer declarative observable pipelines.
* Avoid nested `subscribe`.
* Avoid manual subscriptions where `async`, signals or framework helpers are sufficient.
* Prefer `takeUntilDestroyed` or equivalent Angular lifecycle integration for manual subscriptions.
* Always consider subscription lifetime.
* Avoid memory leaks from unmanaged subscriptions.
* Use the correct flattening operator for the required semantics.
* Do not use `switchMap`, `mergeMap`, `concatMap` or `exhaustMap` interchangeably.
* Avoid unnecessary `Subject` usage.
* Prefer exposing observables instead of exposing mutable subjects.
* Prefer `BehaviorSubject` only when a current value is actually required.
* Avoid excessive observable chains for simple state.
* Avoid converting repeatedly between signals and observables without need.
## Dependency Injection
* Prefer Angular dependency injection for application services.
* Keep injected dependencies minimal.
* Avoid service locator patterns.
* Prefer `inject()` where it improves readability and is consistent with the project.
* Do not inject services that are not used.
* Scope services intentionally.
* Prefer application-wide singletons only for truly shared stateless or coordinated state.
* Avoid storing request-specific or component-specific mutable state in root services.
* Use injection tokens for configuration or abstractions where appropriate.
* Do not create interfaces only to satisfy dependency injection when no abstraction is needed.
## Services
* Keep services focused on a clear responsibility.
* Avoid large catch-all services.
* Separate API access, domain logic and UI state where practical.
* Avoid leaking transport models throughout the application.
* Do not expose mutable internal state directly.
* Prefer readonly APIs for state consumers.
* Avoid hidden side effects.
* Keep service methods predictable.
* Do not use services merely to move poorly structured component code elsewhere.
## HTTP and APIs
* Keep API access centralized and strongly typed.
* Prefer dedicated API clients or data-access services.
* Do not use `any` for API responses.
* Treat all server responses as untrusted at runtime.
* Validate external data when the contract is security- or correctness-critical.
* Keep DTOs separate from domain models when their responsibilities differ.
* Avoid duplicate API calls.
* Cache only when the invalidation strategy is clear.
* Avoid manual URL string construction when typed helpers or centralized endpoints are available.
* Use interceptors only for cross-cutting concerns.
* Do not put unrelated business logic into HTTP interceptors.
* Handle cancellation where appropriate.
* Handle expected error states explicitly.
## Forms
* Prefer reactive forms for non-trivial forms.
* Keep forms strongly typed.
* Avoid untyped forms.
* Keep validation rules centralized and reusable where practical.
* Validate on both client and server where required.
* Never treat client-side validation as a security boundary.
* Keep form state separate from domain state when useful.
* Avoid large components that combine layout, validation, persistence and business logic.
* Display validation errors consistently.
* Preserve user input when recoverable errors occur.
## Routing
* Keep route definitions explicit and predictable.
* Prefer lazy loading for larger feature areas.
* Avoid loading large feature bundles eagerly without need.
* Use route guards only for navigation behavior, not as a security boundary.
* Authorization must still be enforced on the backend.
* Keep resolvers focused.
* Avoid expensive work during navigation unless required.
* Keep route parameters strongly typed at application boundaries where practical.
* Do not rely on client-side routing state for sensitive authorization decisions.
## Performance
* Use `OnPush`.
* Use stable tracking in loops.
* Avoid unnecessary change detection triggers.
* Avoid repeated expensive template calculations.
* Avoid unnecessary subscriptions.
* Avoid unnecessary DOM rendering.
* Lazy-load large features and heavy dependencies where appropriate.
* Avoid large initial bundles.
* Avoid importing full libraries when only a small part is required.
* Avoid unnecessary deep cloning.
* Avoid unnecessary object and array recreation in hot paths.
* Keep state updates targeted.
* Avoid unnecessary global state updates.
* Measure bundle size and runtime performance before micro-optimizing.
* Prefer architectural improvements over template-level micro-optimizations.
## Security
* Treat all external data as untrusted.
* Never bypass Angular sanitization without a verified reason.
* Avoid direct DOM manipulation.
* Avoid `innerHTML` with untrusted content.
* Avoid `bypassSecurityTrust*` unless explicitly required and the input is fully controlled.
* Never expose secrets in frontend code.
* Never store sensitive credentials in the Angular application.
* Do not rely on frontend checks for authorization.
* Enforce authentication and authorization on the backend.
* Avoid leaking sensitive information through logs or error messages.
* Use secure cookie or token handling according to the application's authentication architecture.
* Avoid storing sensitive tokens in insecure browser storage without a deliberate security decision.
* Do not disable security controls for convenience.
## DOM and Browser APIs
* Prefer Angular APIs and declarative templates over direct DOM manipulation.
* Use `Renderer2` only when direct rendering abstraction is actually needed.
* Avoid accessing globals directly when it harms testability or SSR compatibility.
* Consider SSR and hydration compatibility for browser-specific code.
* Guard access to `window`, `document`, `localStorage` and similar browser-only APIs when SSR is supported.
* Clean up event listeners, observers and timers.
* Avoid layout thrashing in performance-sensitive code.
## Accessibility
* Use semantic HTML.
* Preserve keyboard navigation.
* Ensure interactive elements are actually interactive elements.
* Do not replace buttons with clickable `div` elements.
* Provide labels for form controls.
* Maintain visible focus behavior.
* Use ARIA only when native HTML semantics are insufficient.
* Avoid unnecessary custom widgets.
* Keep accessible names and states synchronized with UI state.
## Styling
* Keep styles scoped and predictable.
* Avoid unnecessary global CSS.
* Follow the project's styling strategy consistently.
* Avoid excessive specificity.
* Avoid `!important` unless there is a concrete reason.
* Prefer reusable design tokens and shared styles over duplicated magic values.
* Keep component styles focused on component concerns.
* Avoid styling based on fragile DOM structure.
* Do not mix multiple styling approaches without need.
## Testing
* Test behavior, not implementation details.
* Prefer focused component tests.
* Test critical user interactions.
* Test services and domain logic independently where useful.
* Avoid brittle tests coupled to internal structure.
* Avoid excessive mocking.
* Mock external boundaries rather than internal implementation details.
* Keep tests deterministic.
* Avoid time-dependent tests without controlled clocks.
* Avoid network-dependent tests without proper isolation.
* Keep test setup minimal and readable.
* Update tests when refactoring changes structure but not behavior.
## Architecture
* Keep UI, application, domain and data-access concerns separated where practical.
* Organize code by feature rather than by technical file type when it improves cohesion.
* Avoid circular dependencies.
* Avoid cross-feature imports without a clear contract.
* Keep shared code genuinely shared.
* Do not move feature-specific logic into generic shared modules.
* Avoid dumping unrelated helpers into global utility files.
* Keep public APIs of feature areas small.
* Avoid exposing internal implementation details across feature boundaries.
* Prefer local ownership of state and logic.
## Code Quality
* Use strict TypeScript settings.
* Avoid `any`.
* Avoid unnecessary type assertions.
* Avoid non-null assertions unless safety is guaranteed.
* Prefer modern, readable syntax.
* Use descriptive names.
* Avoid vague names such as `data`, `item`, `value` or `temp` when better names exist.
* Remove dead code.
* Remove unused imports and dependencies.
* Remove commented-out code instead of keeping it in source files.
* Do not add comments unless the user explicitly requests them.
* Treat Angular, TypeScript and lint warnings seriously.
* Do not suppress diagnostics without a concrete reason.
* Prefer correctness, security and maintainability over cleverness.
## Dependency Rules
* Prefer Angular and browser platform capabilities before adding third-party libraries.
* Do not add dependencies without a clear benefit.
* Avoid libraries that duplicate existing framework functionality.
* Avoid abandoned or poorly maintained packages.
* Keep Angular package versions aligned.
* Do not mix incompatible Angular package versions.
* Respect the existing lockfile and package manager.
* Avoid unrelated dependency upgrades.
## Performance Priority
Prioritize Angular performance work in this order:
* Application architecture
* Network and API behavior
* Bundle size and lazy loading
* State architecture
* Change detection
* Rendering and DOM complexity
* RxJS and subscription behavior
* Memory allocations
* CPU micro-optimizations
Never optimize based purely on assumptions.
## Safety Rule
* Angular frontend code is never a security boundary.
* Client-side validation, guards, hidden controls and disabled UI elements do not replace backend enforcement.
* Do not bypass Angular's built-in security mechanisms without a verified and explicit reason.
* Prefer safe framework defaults over custom low-level behavior.