agent-frontend
npx skills add https://github.com/tidemann/st44-home --skill agent-frontend
Agent 安装分布
Skill 文档
Frontend Development Skill
Expert in Angular 21+ frontend development following project conventions.
When to Use This Skill
Use this skill when:
- Implementing UI components or pages
- Creating or modifying Angular services
- Working with forms and validation
- Implementing routing or guards
- Any frontend-related task
Core Principles
Angular 21+ Patterns
- Standalone components only (no NgModules)
- Signals for state (
signal(),computed()) - OnPush change detection (always)
- inject() for DI (not constructor injection)
- Native control flow (
@if,@for,@switch) - input()/output() functions (not decorators)
Naming Conventions
- camelCase everywhere – variables, properties, all naming
- NEVER use snake_case
Mandatory Local Testing (CRITICAL)
BEFORE EVERY PUSH, run ALL checks from apps/frontend:
cd apps/frontend
# 1. Lint check
npm run lint
# 2. Format check
npm run format:check
# 3. Tests
npm run test:ci
# 4. Build
npm run build
If ANY check fails:
- STOP – Do not proceed
- Fix the issue
- Re-run ALL checks
- Only push when ALL pass
Why: CI feedback loop takes 3-5 minutes vs local checks in <1 minute. Debugging locally is 10x faster.
Component Guidelines
Component Size Management
- Small components (<50 lines template): Inline templates OK
- All components: CSS in separate files (NEVER inline styles)
- Large components (>200 lines): Break into smaller components
- Large controllers (>100 lines): Extract utility functions
TypeScript Best Practices
- NEVER use
any– useunknowninstead - Prefer type inference when obvious
- Use proper generics for type safety
- Leverage TypeScript utility types (Partial, Required, Pick, Omit)
Templates
Control Flow
// â
CORRECT - Native control flow
@if (user()) {
<p>Welcome {{user().name}}</p>
}
@for (item of items(); track item.id) {
<div>{{item.name}}</div>
}
// â WRONG - Old structural directives
*ngIf="user"
*ngFor="let item of items"
Class Bindings
<!-- â
CORRECT -->
<div [class.active]="isActive()">
<!-- â WRONG -->
<div [ngClass]="{'active': isActive()}"></div>
</div>
State Management
â ï¸ CRITICAL – Read Before Implementing:
Shared State (Multi-Component)
If data is needed across multiple pages/components:
- MUST use centralized store (NgRx SignalStore or custom signal-based store)
- NEVER duplicate API calls across components
- Examples: household, user, tasks, assignments
Local Component State
// Simple local state with signals
export class MyComponent {
// Local state
private count = signal(0);
// Derived state
doubleCount = computed(() => this.count() * 2);
// Update state
increment() {
this.count.update((c) => c + 1);
// Or: this.count.set(5);
}
}
Async Data Loading
Use AsyncState utility instead of manual loading/error/data signals:
import { AsyncState } from '../utils/async-state';
export class MyComponent {
protected readonly dataState = new AsyncState<Data[]>();
async loadData(): Promise<void> {
await this.dataState.execute(async () => {
return this.dataService.getData();
});
}
}
Benefits: Eliminates 15+ lines of boilerplate, type-safe, consistent
localStorage
NEVER use localStorage directly – use StorageService:
// â WRONG
localStorage.setItem('key', JSON.stringify(value));
// â
CORRECT
this.storageService.set('key', value);
See: GitHub Issues #255 (State), #258 (AsyncState), #259 (Storage)
Services
// Use inject() instead of constructor injection
export class MyService {
private http = inject(HttpClient);
private router = inject(Router);
getData() {
return this.http.get('/api/data');
}
}
Accessibility (WCAG AA Compliance)
- All implementations MUST pass AXE checks
- Implement proper focus management
- Ensure sufficient color contrast
- Add appropriate ARIA attributes
- Support keyboard navigation
Workflow
- Read the optimized agent spec:
.claude/agents/agent-frontend.md - Understand requirements and acceptance criteria
- Research existing patterns in the codebase
- Implement following all conventions above
- Test locally with ALL checks (lint, format, tests, build)
- Only then commit and push
Common Patterns
Creating Components
# Always use Angular CLI
ng generate component my-component
# Or shorthand:
ng g c my-component
API Integration
export class DataService {
private api = inject(ApiService);
async fetchData(): Promise<Data[]> {
return this.api.get<Data[]>('/api/data');
}
}
Forms
export class FormComponent {
form = new FormGroup({
name: new FormControl('', [Validators.required]),
email: new FormControl('', [Validators.required, Validators.email]),
});
onSubmit() {
if (this.form.invalid) return;
// Process form
}
}
Reference Files
For detailed patterns and examples:
.github/agents/frontend-agent.md– Complete agent specification with architectural improvementsCLAUDE.md– Project-wide conventions
Specialized Skills (use these for specific patterns):
.claude/skills/state-management/– Centralized stores, AsyncState, localStorage abstraction.claude/skills/http-interceptors/– Auth, error handling, retry logic, caching.claude/skills/testing-infrastructure/– Fixtures, mocks, component harness.claude/skills/storybook/– Component development and visual testing
Architecture Improvement Issues (reference these for best practices):
- #253: Routing Architecture (layout components)
- #254: Performance Optimizations (pagination, virtual scrolling, caching)
- #255: State Management (centralized store)
- #256: Service Layer Boundaries (single responsibility)
- #257: HTTP Layer Improvements (interceptors)
- #258: Eliminate Code Duplication (AsyncState utility)
- #259: Abstract localStorage (StorageService)
- #260: Component Organization (presentational vs container)
- #261: Testing Infrastructure (shared utilities)
Success Criteria
Before marking work complete:
- All local checks pass (lint, format, tests, build)
- Accessibility verified with AXE
- Follows Angular 21+ patterns
- Uses signals for state management
- camelCase naming throughout
- No
anytypes used