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-4/

{
  "context": "Tests whether the agent proactively applies Angular best practices when building a settings page with nested routing. The task describes only business requirements -- it says nothing about lazy loading, standalone components, inject(), or reactive forms. The agent should apply these patterns on its own.",
  "type": "weighted_checklist",
  "checklist": [
    {
      "name": "Lazy loaded child routes",
      "description": "Child routes use loadComponent for code splitting instead of eagerly importing and referencing component classes directly in the route config.",
      "max_score": 14
    },
    {
      "name": "All components standalone",
      "description": "Every component (settings layout, profile, notifications, security) uses standalone: true. No NgModule classes are created.",
      "max_score": 12
    },
    {
      "name": "inject() for dependency injection",
      "description": "Any injected services (Router, ActivatedRoute, etc.) use the inject() function, NOT constructor parameter injection.",
      "max_score": 12
    },
    {
      "name": "Reactive forms for profile and security",
      "description": "The profile and security forms use ReactiveFormsModule with FormGroup and FormControl, NOT template-driven forms with ngModel.",
      "max_score": 12
    },
    {
      "name": "OnPush change detection",
      "description": "Components use changeDetection: ChangeDetectionStrategy.OnPush.",
      "max_score": 8
    },
    {
      "name": "New control flow syntax",
      "description": "Templates use @if and @for (with track where applicable) instead of *ngIf and *ngFor structural directives.",
      "max_score": 8
    },
    {
      "name": "Default redirect to profile",
      "description": "The route configuration includes a redirect from the empty child path to 'profile'.",
      "max_score": 8
    },
    {
      "name": "Validators on form controls",
      "description": "Form controls include appropriate validators (Validators.required, Validators.email, etc.) and the submit handler checks form.valid.",
      "max_score": 10
    },
    {
      "name": "Accessibility on forms",
      "description": "Form inputs include accessibility attributes such as aria-required, label-input association via for/id, and aria-invalid bindings.",
      "max_score": 10
    },
    {
      "name": "RouterLink for navigation",
      "description": "The settings sidebar/tab navigation uses routerLink with routerLinkActive for highlighting, properly imported in the standalone component.",
      "max_score": 6
    }
  ]
}

evals

tile.json