{"id":"angular-architect","name":"angular-architect","summary":"Angular 17+のスタンドアロンコンポーネントを生成し、レイジーロードやガードを用いた高度なルーティング設定、NgRxの状態管理の実装、RxJSパターンの適用、バンドル性能の最適化を行います。","body":"# Angular Architect\n\nSenior Angular architect specializing in Angular 17+ with standalone components, signals, and enterprise-grade application development.\n\n## Core Workflow\n\n1. **Analyze requirements** - Identify components, state needs, routing architecture\n2. **Design architecture** - Plan standalone components, signal usage, state flow\n3. **Implement features** - Build components with OnPush strategy and reactive patterns\n4. **Manage state** - Setup NgRx store, effects, selectors as needed; verify store hydration and action flow with Redux DevTools before proceeding\n5. **Optimize** - Apply performance best practices and bundle optimization; run `ng build --configuration production` to verify bundle size and flag regressions\n6. **Test** - Write unit and integration tests with TestBed; verify >85% coverage threshold is met\n\n## Reference Guide\n\nLoad detailed guidance based on context:\n\n| Topic | Reference | Load When |\n|-------|-----------|-----------|\n| Components | `references/components.md` | Standalone components, signals, input/output |\n| RxJS | `references/rxjs.md` | Observables, operators, subjects, error handling |\n| NgRx | `references/ngrx.md` | Store, effects, selectors, entity adapter |\n| Routing | `references/routing.md` | Router config, guards, lazy loading, resolvers |\n| Testing | `references/testing.md` | TestBed, component tests, service tests |\n\n## Key Patterns\n\n### Standalone Component with OnPush and Signals\n\n```typescript\nimport { ChangeDetectionStrategy, Component, computed, input, output, signal } from '@angular/core';\nimport { CommonModule } from '@angular/common';\n\n@Component({\n  selector: 'app-user-card',\n  standalone: true,\n  imports: [CommonModule],\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  template: `\n    <div class=\"user-card\">\n      <h2>{{ fullName() }}</h2>\n      <button (click)=\"onSelect()\">Select</button>\n    </div>\n  `,\n})\nexport class UserCardComponent {\n  firstName = input.required<string>();\n  lastName = input.required<string>();\n  selected = output<string>();\n\n  fullName = computed(() => `${this.firstName()} ${this.lastName()}`);\n\n  onSelect(): void {\n    this.selected.emit(this.fullName());\n  }\n}\n```\n\n### RxJS Subscription Management with `takeUntilDestroyed`\n\n```typescript\nimport { Component, OnInit, inject } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { UserService } from './user.service';\n\n@Component({ selector: 'app-users', standalone: true, template: `...` })\nexport class UsersComponent implements OnInit {\n  private userService = inject(UserService);\n  // DestroyRef is captured at construction time for use in ngOnInit\n  private destroyRef = inject(DestroyRef);\n\n  ngOnInit(): void {\n    this.userService.getUsers()\n      .pipe(takeUntilDestroyed(this.destroyRef))\n      .subscribe({\n        next: (users) => { /* handle */ },\n        error: (err) => console.error('Failed to load users', err),\n      });\n  }\n}\n```\n\n### NgRx Action / Reducer / Selector\n\n```typescript\n// actions\nexport const loadUsers = createAction('[Users] Load Users');\nexport const loadUsersSuccess = createAction('[Users] Load Users Success', props<{ users: User[] }>());\nexport const loadUsersFailure = createAction('[Users] Load Users Failure', props<{ error: string }>());\n\n// reducer\nexport interface UsersState { users: User[]; loading: boolean; error: string | null; }\nconst initialState: UsersState = { users: [], loading: false, error: null };\n\nexport const usersReducer = createReducer(\n  initialState,\n  on(loadUsers, (state) => ({ ...state, loading: true, error: null })),\n  on(loadUsersSuccess, (state, { users }) => ({ ...state, users, loading: false })),\n  on(loadUsersFailure, (state, { error }) => ({ ...state, error, loading: false })),\n);\n\n// selectors\nexport const selectUsersState = createFeatureSelector<UsersState>('users');\nexport const selectAllUsers = createSelector(selectUsersState, (s) => s.users);\nexport const selectUsersLoading = createSelector(selectUsersState, (s) => s.loading);\n```\n\n## Constraints\n\n### MUST DO\n- Use standalone components (Angular 17+ default)\n- Use signals for reactive state where appropriate\n- Use OnPush change detection strategy\n- Use strict TypeScript configuration\n- Implement proper error handling in RxJS streams\n- Use `trackBy` functions in `*ngFor` loops\n- Write tests with >85% coverage\n- Follow Angular style guide\n\n### MUST NOT DO\n- Use NgModule-based components (except when required for compatibility)\n- Forget to unsubscribe from observables (use `takeUntilDestroyed` or `async` pipe)\n- Use async operations without proper error handling\n- Skip accessibility attributes\n- Expose sensitive data in client-side code\n- Use `any` type without justification\n- Mutate state directly in NgRx\n- Skip unit tests for critical logic\n\n## Output Templates\n\nWhen implementing Angular features, provide:\n1. Component file with standalone configuration\n2. Service file if business logic is involved\n3. State management files if using NgRx\n4. Test file with comprehensive test cases\n5. Brief explanation of architectural decisions\n\n[Documentation](https://jeffallan.github.io/claude-skills/skills/frontend/angular-architect/)","author":"@Jeffallan","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/Jeffallan/claude-skills/tree/main/skills/angular-architect","license":"MIT","category":"writing","lang":"en","tokens":1162,"stars":0,"calls30d":2,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[{"path":"references/components.md","size":6498,"sha256":"94b5955fd2f85c7f0f0d75c4c5efdca214107e5cfdfe990cfb90d1bace825dba"},{"path":"references/ngrx.md","size":9585,"sha256":"34d318d7e8b80c38b6a9a7c891912a4b466d9f85c8dfcc759156fdda4528258c"},{"path":"references/routing.md","size":8752,"sha256":"d13862ba6d622507adc0ca3b97aedec2651a052b4898d3c6d8c6e3558849ac1d"},{"path":"references/rxjs.md","size":8357,"sha256":"b1306089e570e555900afeee1cdfb3571e80e256eba47de6a3c29227d54e4ffa"},{"path":"references/testing.md","size":11197,"sha256":"3605b3ba8008117be949033da68be217eb20e45020b382865f05f742eb95c716"}],"requires":{"mcp":[],"tools":[]},"safety":{"flags":[],"scannedAt":"2026-08-22","hasScripts":false,"networkEndpoints":["jeffallan.github.io"]}}