
Angular Best Practices
Apply Angular 21 conventions—standalone components, signals, OnPush, reactive forms, and strict TypeScript—when agents generate or refactor UI code.
Overview
angular-best-practices is an agent skill most often used in Build (frontend) (also Ship review) that enforces Angular 21 patterns including signals, standalone components, and reactive forms.
Install
npx skills add https://github.com/boise-state-development/agentcore-public-stack --skill angular-best-practicesWhat is this skill?
- Angular 21 defaults: standalone components without explicit standalone flag
- Signal-based state: input(), output(), computed(); no signal mutate—use update/set
- OnPush change detection and small single-responsibility components
- Reactive forms over template-driven; class/style bindings over ngClass/ngStyle
- Strict typing: avoid any, prefer unknown; host object instead of HostBinding/HostListener
Adoption & trust: 713 installs on skills.sh; 9 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your agent keeps generating legacy Angular patterns—NgModules, any types, template-driven forms—that fight Angular 21 defaults and hurt performance and a11y.
Who is it for?
Solo builders on Angular 21 greenfield or migration work who want agent output to match current framework idioms out of the box.
Skip if: React, Vue, or Angular versions below the signal/standalone era when your repo is still NgModule-centric by policy.
When should I use this skill?
When creating Angular components, services, templates, or performing any Angular frontend development work.
What do I get? / Deliverables
Angular files follow signal-based state, OnPush standalone components, strict typing, and reactive forms so UI code is consistent and easier to review before ship.
- Components and services following documented patterns
- Templates using reactive forms and signal APIs
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Primary shelf is Build frontend because the skill triggers on component, service, and template work—the main implementation surface for Angular apps. Frontend subphase covers SPA structure, templates, state, and forms; the skill is a rule set for every Angular touchpoint in that layer.
Where it fits
Spike a landing-page Angular shell with standalone components and OnPush so the prototype does not need a later rewrite.
Generate a feature module as small standalone components with signal inputs and reactive forms.
Refactor agent output that used ngClass and any types into class bindings and unknown-safe handlers before merge.
How it compares
Opinionated Angular 21 style guide for agents—not a generic CSS or REST API integration skill.
Common Questions / FAQ
Who is angular-best-practices for?
Indie developers and agent users building Angular 21 frontends who need consistent component, signal, and form patterns without re-pasting style rules every session.
When should I use angular-best-practices?
During Build frontend for new components and services; during Ship review when refactoring agent-generated templates; during Validate prototype when spike UI must not lock in deprecated APIs.
Is angular-best-practices safe to install?
It is documentation-style guidance only; still review the Security Audits panel on this Prism page and diff agent changes like any other skill-driven edits.
SKILL.md
READMESKILL.md - Angular Best Practices
# Angular 21 Best Practices ## TypeScript - Use strict type checking - Prefer type inference when type is obvious - Avoid `any`; use `unknown` when type is uncertain ## Components - Always use standalone components (do NOT set `standalone: true` — it's the default in v20+) - Set `changeDetection: ChangeDetectionStrategy.OnPush` - Use `input()` and `output()` functions instead of decorators - Use `computed()` for derived state - Keep components small and single-responsibility - Prefer inline templates for small components - Use Reactive forms over Template-driven - Use `class` bindings instead of `ngClass` - Use `style` bindings instead of `ngStyle` - For external templates/styles, use paths relative to the component TS file - Do NOT use `@HostBinding`/`@HostListener` — use the `host` object in the decorator instead ## State Management with Signals - Use signals for local component state - Use `computed()` for derived state - Keep state transformations pure and predictable - Do NOT use `mutate` on signals — use `update` or `set` instead For complex derived state patterns, see [references/signal-patterns.md](references/signal-patterns.md). ## Resources (Async Data) Use `resource()` for async data fetching with signals: ```typescript const userResource = resource({ params: () => ({ id: userId() }), loader: ({ params, abortSignal }) => fetch(`/api/users/${params.id}`, { signal: abortSignal }), }); const userName = computed(() => userResource.hasValue() ? userResource.value().name : undefined); ``` Key `resource` patterns: - `params` returns `undefined` → loader doesn't run, status becomes `'idle'` - Use `abortSignal` to cancel in-flight requests - Check `hasValue()` before accessing `value()` to handle loading/error states - Status values: `'idle'`, `'loading'`, `'reloading'`, `'resolved'`, `'error'`, `'local'` ## Templates - Use native control flow: `@if`, `@for`, `@switch` (NOT `*ngIf`, `*ngFor`, `*ngSwitch`) - Use async pipe for observables - Keep templates simple — no complex logic - Do NOT use arrow functions in templates (not supported) - Do NOT assume globals like `new Date()` are available ## Services - Single responsibility per service - Use `providedIn: 'root'` for singletons - Use `inject()` function instead of constructor injection ```typescript @Injectable({ providedIn: 'root' }) export class UserService { private readonly http = inject(HttpClient); } ``` ## Routing - Implement lazy loading for feature routes: ```typescript export const routes: Routes = [ { path: 'admin', loadComponent: () => import('./admin/admin.page').then(m => m.AdminPage), }, ]; ``` ## File Naming - Routable view components: `file-name.page.ts`, `file-name.page.html`, `file-name.page.css` - Regular components: `file-name.component.ts` - Services: `file-name.service.ts` ## Icons (ng-icon) ```typescript import { NgIcon, provideIcons } from '@ng-icons/core'; import { heroSparkles, heroTrash } from '@ng-icons/heroicons/outline'; @Component({ selector: 'app-example', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgIcon], providers: [provideIcons({ heroSparkles, heroTrash })], template: `<ng-icon name="heroSparkles" />`, }) export class ExampleComponent {} ``` ## Images - Use `NgOptimizedImage` for all static images - `NgOptimizedImage` does NOT work for inline base64 images ## Styling - Use Tailwind 4.1 for CSS (see tailwind skill if available) - Angular CDK is available when needed ## Accessibility - MUST pass all AXE checks - MUST meet WCAG AA minimums: focus man