CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl-labs/angular-best-practices

Angular patterns — standalone components, signals, inject(), reactive forms, HTTP interceptors, and new control flow

95

2.75x
Quality

94%

Does it follow best practices?

Impact

99%

2.75x

Average score across 4 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

criteria.jsonevals/scenario-1/

{
  "context": "Tests whether the agent proactively applies Angular best practices when building an employee directory. The task describes only business requirements -- it says nothing about standalone components, signals, OnPush, inject(), or new control flow syntax. The agent should apply these patterns on its own.",
  "type": "weighted_checklist",
  "checklist": [
    {
      "name": "Standalone components",
      "description": "All components use standalone: true in their @Component decorator. No NgModule classes are created.",
      "max_score": 12
    },
    {
      "name": "Signal inputs on card component",
      "description": "The employee card component uses input() or input.required() from @angular/core for its employee data, NOT the @Input() decorator.",
      "max_score": 12
    },
    {
      "name": "inject() for dependency injection",
      "description": "Services and dependencies are injected using the inject() function, NOT constructor parameter injection.",
      "max_score": 12
    },
    {
      "name": "toSignal() for observable conversion",
      "description": "The component converts the service observable to a signal using toSignal() rather than manually subscribing in ngOnInit.",
      "max_score": 12
    },
    {
      "name": "OnPush change detection",
      "description": "Components use changeDetection: ChangeDetectionStrategy.OnPush.",
      "max_score": 10
    },
    {
      "name": "New control flow syntax",
      "description": "Templates use @for (with track expression) and @if instead of *ngFor and *ngIf structural directives.",
      "max_score": 12
    },
    {
      "name": "Service uses catchError with fallback",
      "description": "The HTTP service method pipes through catchError and returns a fallback value (e.g. empty array) rather than letting errors propagate unhandled.",
      "max_score": 10
    },
    {
      "name": "Service uses map() to unwrap response",
      "description": "The service uses map() in the RxJS pipe to extract the data array from the API response wrapper object, not passing through the raw response.",
      "max_score": 8
    },
    {
      "name": "providedIn root on service",
      "description": "The employee service uses @Injectable({ providedIn: 'root' }).",
      "max_score": 6
    },
    {
      "name": "Track expression in @for",
      "description": "The @for loop uses a track expression (e.g. track employee.id), not trackBy or no tracking.",
      "max_score": 6
    }
  ]
}

evals

scenario-1

criteria.json

task.md

tile.json