Angular development rules for WhyTV project focusing on clean code, signals, and reactive state management with standalone components and lazy loading.
Rules for building the WhyTV application with Angular best practices, reactive state management, and modern standalone component architecture.
Follow these guidelines when writing Angular code for the WhyTV project:
1. Write clean, maintainable code with clear intent
2. Prefer descriptive variable and function names
3. Keep functions small and focused on a single responsibility
4. Add comments only when necessary to explain "why", not "what"
1. Always prefer async/await over observables for asynchronous operations
2. Use try/catch blocks for error handling with async/await
3. Avoid callback patterns in favor of promises
4. Only use observables when truly reactive streams are needed
1. Manage all application state reactively using Angular signals
2. Use ngrx signalState for complex state management (refer to `./docs/signal-state.md`)
3. Leverage computed signals for derived state
4. Use effect() for side effects triggered by signal changes
5. Never mutate signal state directly - always use update methods
1. Always use lodash methods over native array and object methods for consistency
2. Import specific lodash functions rather than the entire library
3. Examples: `_.map()`, `_.filter()`, `_.reduce()`, `_.groupBy()`, etc.
1. Always use standalone components - never use Angular Modules (NgModule)
2. Import dependencies directly in the component decorator
3. Separate HTML, CSS, and TypeScript into individual files for each component
4. Never inline templates or styles except for trivial single-line cases
1. Always use OnPush ChangeDetection strategy for all components
2. Add `changeDetection: ChangeDetectionStrategy.OnPush` to every @Component decorator
3. Rely on signals to trigger change detection automatically
4. Avoid manual change detection triggers
1. Always use the signal-based input() function instead of @Input() decorator
2. Always use the signal-based output() function instead of @Output() decorator
3. Example: `readonly userId = input.required<string>();`
4. Example: `readonly onClick = output<void>();`
1. Always use static route configuration files
2. Lazy-load all components and route files except the initial page load
3. Use `loadComponent` and `loadChildren` in route definitions
4. Structure routes hierarchically for better code splitting
5. Example: `{ path: 'feature', loadComponent: () => import('./feature/feature.component') }`
1. Keep related files together in feature folders
2. Use consistent file naming: `feature-name.component.ts`, `feature-name.component.html`, `feature-name.component.css`
3. Create barrel exports (index.ts) for cleaner imports
4. Organize by feature, not by file type
```typescript
import { Component, ChangeDetectionStrategy, input, output } from '@angular/core';
import { CommonModule } from '@angular/common';
import _ from 'lodash';
@Component({
selector: 'app-example',
standalone: true,
imports: [CommonModule],
templateUrl: './example.component.html',
styleUrl: './example.component.css',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ExampleComponent {
readonly data = input.required<string[]>();
readonly itemClicked = output<string>();
readonly filteredData = computed(() => {
return _.filter(this.data(), item => item.length > 3);
});
}
```
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/whytv-angular-development/raw