Auto-activate for angular.json, *.component.ts, @Component decorator. Expert knowledge for modern Angular with signals, standalone components, control flow blocks, and current migration guidance. Use when building Angular apps with contemporary patterns and when validating version-specific API stability. Not for React (see react), Vue (see vue), or AngularJS (v1).
From flownpx claudepluginhub cofin/flow --plugin flowThis skill uses the workspace's default tool permissions.
references/litestar_vite.mdSearches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
import { Component, signal, computed, effect, input, output } from '@angular/core';
@Component({
selector: 'app-item-list',
standalone: true,
imports: [],
template: `
<h2>{{ title() }} ({{ count() }})</h2>
<ul>
@for (item of items(); track item.id) {
<li (click)="selectItem(item)">{{ item.name }}</li>
}
</ul>
`
})
export class ItemListComponent {
// Input signals
title = input.required<string>();
items = input.required<Item[]>();
// Output
itemSelected = output<Item>();
// Local state
selected = signal<Item | null>(null);
// Computed
count = computed(() => this.items().length);
constructor() {
effect(() => {
console.log('Selected:', this.selected());
});
}
selectItem(item: Item) {
this.selected.set(item);
this.itemSelected.emit(item);
}
}
</example>
<!-- @if -->
@if (loading()) {
<app-spinner />
} @else if (error()) {
<app-error [message]="error()!" />
} @else {
<app-content [data]="data()" />
}
<!-- @for -->
@for (item of items(); track item.id; let i = $index, first = $first) {
<div [class.first]="first">{{ i + 1 }}. {{ item.name }}</div>
} @empty {
<p>No items found</p>
}
<!-- @switch -->
@switch (status()) {
@case ('loading') { <app-spinner /> }
@case ('error') { <app-error /> }
@default { <app-content /> }
}
<!-- @defer -->
@defer (on viewport) {
<app-heavy-component />
} @loading (minimum 200ms) {
<app-skeleton />
}
</example>
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { toSignal } from '@angular/core/rxjs-interop';
@Injectable({ providedIn: 'root' })
export class ItemService {
private http = inject(HttpClient);
items = toSignal(this.http.get<Item[]>('/api/items'), {
initialValue: []
});
async create(item: CreateItemDto): Promise<Item> {
return await firstValueFrom(
this.http.post<Item>('/api/items', item)
);
}
}
</example>
resource() and httpResource() are currently marked experimental in Angular docs. Use only when the project explicitly accepts experimental APIs.
import { resource, signal } from '@angular/core';
@Component({ ... })
export class ItemComponent {
itemId = signal<string>('');
itemResource = resource({
request: () => this.itemId(),
loader: async ({ request: id }) => {
const res = await fetch(`/api/items/${id}`);
return res.json() as Promise<Item>;
}
});
// Usage in template
// itemResource.value() - the data
// itemResource.isLoading() - loading state
// itemResource.error() - error state
}
</example>
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
@Component({
standalone: true,
imports: [ReactiveFormsModule],
template: `
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<input formControlName="name" />
<button type="submit" [disabled]="!form.valid">Save</button>
</form>
`
})
export class ItemFormComponent {
private fb = inject(FormBuilder);
form = this.fb.group({
name: ['', Validators.required],
description: ['']
});
onSubmit() {
if (this.form.valid) {
console.log(this.form.value);
}
}
}
</example>
toSignal() to convert observables@if, @for, @switch)inject() instead of constructor injection@defer for lazy loading heavy componentsAngular builds compile into optimal static files:
ng build
# or litestar assets build for integrated setups
Deploy to Edge nodes or node servers. Ensure triggers are optimized post-hydrate context avoiding layout shifts for deferred blocks.
Example GitHub Actions workflow for building:
name: Angular CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- run: npm ci
- run: npm run build