Files
Personal-Portfolio-Website/AGENTS.md
T

8.5 KiB

Repository Instructions

These instructions apply to this repository unless a more specific AGENTS.md exists in a subdirectory.

Required Verification

  • Always verify changes with:
    • npm run check
    • npm run test
  • If verification fails, npm run fix may help, but do not assume it resolves every issue.
  • Respect the existing tsconfig, ESLint, and Prettier configurations.

Assets

  • Do not edit generated optimized assets by hand.
  • Update source assets in src/assets/unoptimized/.
  • Regenerate optimized assets through the provided scripts, usually via npm run generate:assets or commands that already include asset generation.

Localization

  • Keep localized text synchronized between:
    • src/languages/de.ts
    • src/languages/en.ts
  • When changing user-facing text, update both language files unless the change is intentionally language-specific.

Architecture

  • Create components with exactly one clear responsibility.
  • Keep components focused on UI, user interaction, and view state.
  • Move business logic into focused services.
  • Structure code by feature or domain where appropriate.
  • Put reusable generic elements in shared/.
  • Put domain-specific logic and components in the relevant feature folder.
  • Separate container and presentational components when a view becomes complex.
  • Avoid cyclic dependencies between modules, services, and components.
  • Add abstractions only when at least two real use cases exist.
  • Keep services focused on one business or technical responsibility.

TypeScript

  • Keep strict TypeScript enabled.
  • Use explicit types for public methods, service APIs, and complex return values.
  • Prefer unknown over any when a value still needs validation.
  • Use any only when technically necessary and document the reason.
  • Use union types for fixed value ranges.
  • Use readonly for data that should not be mutated.
  • Prefer const over let when reassignment is not needed.
  • Check null and undefined explicitly before accessing nested values.
  • Separate API DTOs from internal UI or domain models.
  • Map external API data deliberately into internal models.
  • Use clear names for interfaces, types, classes, variables, inputs, and outputs.
  • Avoid type casts when clean type narrowing is possible.
  • Do not suppress type errors with as unknown as.
  • Do not use non-null assertions to hide real nullability problems.

Angular Components

  • Use OnPush change detection unless there is a clear reason not to.
  • Use inputs for externally provided data.
  • Use outputs for events emitted to parent components.
  • Use required inputs when a component cannot work without the data.
  • Keep component classes small and readable.
  • Extract repeated UI blocks into dedicated components.
  • Use lifecycle hooks only when they are necessary.
  • Keep constructors limited to dependency injection.
  • Initialize data clearly and predictably.
  • Do not make god components.
  • Do not mix API access, mapping, business logic, and UI logic in one component.
  • Prefer composition over component inheritance.

Angular State

  • Use Signals for local synchronous component state.
  • Use RxJS for asynchronous data streams and complex event chains.
  • Use services for shared state across multiple components.
  • Keep state as close as possible to where it is needed.
  • Avoid global state when local state is enough.
  • Make state changes explicit and understandable.
  • Avoid hidden state mutation across multiple services.
  • Do not store derived values redundantly when they can be computed.

RxJS

  • Name Observables with a $ suffix.
  • Use the async pipe when a stream is displayed directly in a template.
  • Use switchMap for requests where older requests should be canceled.
  • Use concatMap when ordering must be guaranteed.
  • Use mergeMap when parallel processing is intended.
  • Use exhaustMap when new events should be ignored while work is running.
  • Use combineLatest for dependent live values.
  • Use forkJoin for multiple one-time requests that complete together.
  • Clean up manual subscriptions with takeUntilDestroyed or an equivalent.
  • Handle errors with catchError at the appropriate level.
  • Return controlled fallback state when useful.
  • Do not hide errors that matter for debugging or UX.
  • Do not use subscribe() inside subscribe().
  • Do not use RxJS for trivial synchronous state.
  • Avoid duplicate identical requests from independent subscriptions.

HTTP and API

  • Encapsulate all HTTP calls in services.
  • Define response types for API responses.
  • Use central API configuration through environments or injection tokens.
  • Use interceptors for repeated technical concerns such as auth, headers, and error handling.
  • Implement loading, error, and empty states where requests affect UI.
  • Treat API data defensively when quality is uncertain.
  • Validate or normalize external data before broad UI usage.
  • Avoid duplicate API calls through shared streams or caching where appropriate.
  • Do not hardcode API URLs, tokens, roles, or secrets in components.

Templates

  • Keep templates declarative and easy to read.
  • Use templates for presentation and simple bindings only.
  • Move complex conditions into component code or computed signals.
  • Use @if for conditional rendering.
  • Use @for with track for lists.
  • Track with a stable unique ID when available.
  • Keep binding expressions short.
  • Do not put business rules or complex ternaries into templates.
  • Do not call expensive methods directly from templates.
  • Split large templates into smaller components.

Forms

  • Use Reactive Forms for complex forms.
  • Define validators explicitly.
  • Show validation errors clearly in the UI.
  • Keep form models and API DTOs separate when they differ.
  • Map form data deliberately before submitting.
  • Disable submit while requests are running when duplicate submits are a risk.
  • Surface server-side validation errors in the form.

Styling

  • Prefer component-scoped styling.
  • Use global styles only for truly global rules.
  • Use a consistent design system or consistent utility classes.
  • Reuse classes or components for repeated UI patterns.
  • Account for responsive design in every new view.
  • Prefer semantic HTML before complex CSS.
  • Keep spacing, colors, and font sizes consistent.
  • Use inline styles only for dynamic exceptions.
  • Do not use ::ng-deep as a default solution.
  • Do not create global CSS rules that unintentionally affect other components.
  • Avoid fixed pixel layouts without responsive behavior.

Security

  • Treat all external data as potentially unsafe.
  • Never trust user input without validation.
  • Do not store secrets in frontend code.
  • Implement roles and permissions server-side.
  • Use frontend role checks only for UX, not as a security boundary.
  • Render API-provided HTML only after controlled sanitization.
  • Use bypassSecurityTrustHtml only after explicit security review.
  • Validate redirect URLs against an allowlist.
  • Protect auth flows against XSS and CSRF risks.
  • Store tokens only with a deliberate security concept.

Performance

  • Use lazy loading for larger features.
  • Use OnPush to reduce unnecessary change detection.
  • Use track in lists.
  • Use virtual scrolling for large lists.
  • Avoid expensive computations in templates.
  • Move expensive computations into computed signals, memoization, or services.
  • Avoid large dependencies for small helper functions.
  • Check bundle size impact before adding libraries.
  • Optimize images and assets.
  • Measure performance issues before adding complex optimizations.

Testing

  • Test services that contain business logic.
  • Test complex component logic.
  • Test critical user flows with E2E tests where appropriate.
  • Mock external dependencies in unit tests.
  • Avoid real HTTP calls in unit tests.
  • Write tests with clear behavioral assertions.
  • Cover edge cases and error paths.
  • Keep tests independent from internal implementation details.
  • Use test names that describe behavior.
  • Do not write tests only for coverage.
  • Do not use snapshots as a substitute for concrete assertions.

Code Quality

  • Use ESLint and Prettier.
  • Keep naming consistent.
  • Remove unused code and unused imports.
  • Do not leave commented-out code blocks.
  • Keep changes focused.
  • Write commits with concrete messages.
  • Use comments only for context that is not obvious from the code.
  • Keep files small enough to understand quickly.
  • Follow existing project conventions.
  • Do not leave TODOs without context, a ticket, or a documented decision.
  • Do not add dependencies without checking value, risk, and bundle cost.