Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Generates Angular 17+ standalone components, configures advanced routing with lazy loading and guards, implements NgRx state management, applies RxJS patterns, and optimizes bundle performance. Use when building Angular 17+ applications with standalone components or signals, setting up NgRx stores, establishing RxJS reactive patterns, performance tuning, or writing Angular tests for enterprise apps.
.claude/skills/jeffallan-angular-architect/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 126% | 0% |
| case-13 | ✓→✗ | ▼ Worse | 57% | 0% |
| case-21 | ✓→✓ | = Same ✓ | 111% | 0% |
| case-22 | ✓→✓ | = Same ✓ | 45% | 0% |
| case-05 | ✓→✓ | = Same ✓ | 34% | 0% |
Senior Angular architect specializing in Angular 17+ with standalone components, signals, and enterprise-grade application development.
ng build --configuration production to verify bundle size and flag regressionsLoad detailed guidance based on context:
| Topic | Reference | Load When | |-------|-----------|-----------| | Components | references/components.md | Standalone components, signals, input/output | | RxJS | references/rxjs.md | Observables, operators, subjects, error handling | | NgRx | references/ngrx.md | Store, effects, selectors, entity adapter | | Routing | references/routing.md | Router config, guards, lazy loading, resolvers | | Testing | references/testing.md | TestBed, component tests, service tests |
typescriptimport { ChangeDetectionStrategy, Component, computed, input, output, signal } from '@angular/core'; import { CommonModule } from '@angular/common'; @Component({ selector: 'app-user-card', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: ` <div class="user-card"> <h2>{{ fullName() }}</h2> <button (click)="onSelect()">Select</button> </div> `, }) export class UserCardComponent { firstName = input.required<string>(); lastName = input.required<string>(); selected = output<string>(); fullName = computed(() => `${this.firstName()} ${this.lastName()}`); onSelect(): void { this.selected.emit(this.fullName()); } }
takeUntilDestroyedtypescriptimport { Component, OnInit, inject } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { UserService } from './user.service'; @Component({ selector: 'app-users', standalone: true, template: `...` }) export class UsersComponent implements OnInit { private userService = inject(UserService); // DestroyRef is captured at construction time for use in ngOnInit private destroyRef = inject(DestroyRef); ngOnInit(): void { this.userService.getUsers() .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe({ next: (users) => { /* handle */ }, error: (err) => console.error('Failed to load users', err), }); } }
typescript// actions export const loadUsers = createAction('[Users] Load Users'); export const loadUsersSuccess = createAction('[Users] Load Users Success', props<{ users: User[] }>()); export const loadUsersFailure = createAction('[Users] Load Users Failure', props<{ error: string }>()); // reducer export interface UsersState { users: User[]; loading: boolean; error: string | null; } const initialState: UsersState = { users: [], loading: false, error: null }; export const usersReducer = createReducer( initialState, on(loadUsers, (state) => ({ ...state, loading: true, error: null })), on(loadUsersSuccess, (state, { users }) => ({ ...state, users, loading: false })), on(loadUsersFailure, (state, { error }) => ({ ...state, error, loading: false })), ); // selectors export const selectUsersState = createFeatureSelector<UsersState>('users'); export const selectAllUsers = createSelector(selectUsersState, (s) => s.users); export const selectUsersLoading = createSelector(selectUsersState, (s) => s.loading);
trackBy functions in *ngFor loopstakeUntilDestroyed or async pipe)any type without justificationWhen implementing Angular features, provide:
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-21 | pass→pass | 11,339 | 16,981 | +50% | 1 | 1 | 0% | 2,597 | 5,469 | +111% | 0 | 0 | — |
case-22 | pass→pass | 12,302 | 13,837 | +12% | 1 | 1 | 0% | 3,020 | 4,390 | +45% | 0 | 0 | — |
case-03 | fail→fail | 24,309 | 25,695 | +6% | 1 | 1 | 0% | 5,745 | 7,445 | +30% | 0 | 0 | — |
case-01 | fail→fail | 22,419 | 22,356 | -0% | 1 | 1 | 0% | 5,459 | 6,536 | +20% | 0 | 0 | — |
case-02 | fail→fail | 28,069 | 24,898 | -11% | 1 | 1 | 0% | 6,201 | 7,460 | +20% | 0 | 0 | — |
case-04 | fail→pass | 11,796 | 18,189 | +54% | 1 | 1 | 0% | 2,482 | 5,620 | +126% | 0 | 0 | — |
case-05 | pass→pass | 12,292 | 8,390 | -32% | 1 | 1 | 0% | 2,349 | 3,138 | +34% | 0 | 0 | — |
case-06 | pass→pass | 18,401 | 28,414 | +54% | 1 | 1 | 0% | 4,184 | 7,428 | +78% | 0 | 0 | — |
case-07 | pass→pass | 13,336 | 17,705 | +33% | 1 | 1 | 0% | 2,903 | 5,949 | +105% | 0 | 0 | — |
case-12 | pass→pass | 5,962 | 1,933 | -68% | 1 | 1 | 0% | 1,147 | 1,558 | +36% | 0 | 0 | — |
case-08 | pass→pass | 12,109 | 11,682 | -4% | 1 | 1 | 0% | 2,547 | 3,694 | +45% | 0 | 0 | — |
case-09 | pass→pass | 8,542 | 8,300 | -3% | 1 | 1 | 0% | 1,842 | 3,160 | +72% | 0 | 0 | — |
case-10 | pass→pass | 5,511 | 3,691 | -33% | 1 | 1 | 0% | 1,097 | 1,913 | +74% | 0 | 0 | — |
case-11 | pass→pass | 7,917 | 4,198 | -47% | 1 | 1 | 0% | 1,456 | 2,111 | +45% | 0 | 0 | — |
case-13 | pass→fail | 17,276 | 18,188 | +5% | 1 | 1 | 0% | 3,390 | 5,333 | +57% | 0 | 0 | — |
case-14 | pass→pass | 11,202 | 15,422 | +38% | 1 | 1 | 0% | 2,799 | 4,929 | +76% | 0 | 0 | — |
case-15 | pass→pass | 7,675 | 5,221 | -32% | 1 | 1 | 0% | 1,250 | 2,321 | +86% | 0 | 0 | — |
case-16 | pass→pass | 8,215 | 7,090 | -14% | 1 | 1 | 0% | 1,641 | 2,788 | +70% | 0 | 0 | — |
case-17 | fail→fail | 26,240 | 23,658 | -10% | 1 | 1 | 0% | 6,164 | 7,423 | +20% | 0 | 0 | — |
case-18 | pass→pass | 27,374 | 24,755 | -10% | 1 | 1 | 0% | 5,824 | 7,264 | +25% | 0 | 0 | — |
case-19 | pass→pass | 11,938 | 18,018 | +51% | 1 | 1 | 0% | 2,591 | 5,562 | +115% | 0 | 0 | — |
case-20 | pass→pass | 16,995 | 14,140 | -17% | 1 | 1 | 0% | 2,820 | 3,797 | +35% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of 0 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.