agentleFS
nimadorostkarnimadorostkar/Claude-Skills-collection/skills/frontend/angular/SKILL.md

angular

Skill33 starsChanged 34 days agoMITView on GitHub

Use when building Angular applications. Covers standalone components, signals, RxJS discipline, change detection, dependency injection, and the patterns that keep large Angular codebases fast. Trigger on "subscription memory leak", "migrate to standalone components", "change detection is slow", "signals or rxjs for this state". Do not use for app-wide folder and state structure — see the frontend-architecture skill.

15 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

2 rules. 0 are common, 1 is distinctive, and 1 is very specific to this project.

  • 0

    Common

    Most of the 14 edited versions we read keep these.

  • 1

    Distinctive

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    No manual subscriptions without a matching teardown.

    line 41
  2. Very specific:

    Do not call methods from the template ({{ getTotal() }}).

    line 53

“Common” is measured: kept by at least 6 in 10 of the 14 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Angular

Purpose

Build modern Angular — standalone components, signals for state, RxJS only where streams genuinely help — and keep change detection from becoming the bottleneck it becomes by default.

When to Use

  • Building or reviewing an Angular 17+ application.
  • Migrating from NgModules to standalone components, or from RxJS state to signals.
  • Diagnosing performance problems caused by change detection.
  • Preventing subscription leaks.

Capabilities

  • Standalone components, directives, and functional route guards.
  • Signals: signal, computed, effect, and toSignal interop with RxJS.
  • Change detection: OnPush, zoneless, and what triggers a check.
  • RxJS operators for the cases where a stream is the right model.
  • Dependency injection with inject() and provider scoping.

Inputs

  • The component or feature, and its data sources.
  • Angular version, and whether zone.js is still in use.
  • The performance symptom, if any.

Outputs

  • Standalone components with OnPush change detection.
  • State in signals; asynchronous events in observables, converted at the boundary.
  • No manual subscriptions without a matching teardown.

Workflow

  1. Go standalone — NgModules are legacy. Standalone components with explicit imports make the dependency graph readable.
  2. Use signals for state — Synchronous, glitch-free, and integrated with change detection. Reserve RxJS for genuine streams: HTTP, WebSockets, user-input debouncing.
  3. Set OnPush everywhere — Default change detection re-checks the entire component tree on every event. OnPush limits it to inputs that actually changed.
  4. Convert at the boundary — toSignal(this.http.get(...)) brings an observable into the signal world. Do not maintain state in a BehaviorSubject and mirror it into a signal.
  5. Never subscribe manually without teardown — takeUntilDestroyed() or the async pipe. A subscription without an unsubscribe is a leak with a component attached.

Best Practices

  • Do not call methods from the template ({{ getTotal() }}). They run on every change-detection cycle. Use a computed signal.
  • subscribe() inside subscribe() is a nested-subscription bug. Flatten with switchMap, mergeMap, or concatMap — chosen for the cancellation semantics you actually want.
  • switchMap cancels the previous request, which is correct for typeahead and wrong for saving a form. Pick deliberately.
  • Provide services at the component level when the state is component-scoped; providedIn: 'root' makes it a singleton shared by every consumer.
  • effect() is for side effects only. Writing to a signal inside an effect creates a loop that Angular will warn about, and it usually means you wanted computed.
  • Zoneless change detection (Angular 18+) removes zone.js entirely and requires signals throughout. It is worth targeting for new applications.

Examples

Signal state with an RxJS boundary:

@Component({
  selector: "app-order-list",
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [OrderCardComponent],
  template: `
    @if (orders.isLoading()) {
      <app-skeleton />
    } @else {
      @for (order of visibleOrders(); track order.id) {
        <app-order-card [order]="order" />
      } @empty {
        <p>No orders match this filter.</p>
      }
    }
  `,
})
export class OrderListComponent {
  private readonly api = inject(OrderApi);

  readonly status = signal<OrderStatus>("open");
  readonly orders = rxResource({
    request: () => ({ status: this.status() }),
    loader: ({ request }) => this.api.list(request.status),
  });

  // Derived state, recomputed only when its dependencies change.
  readonly visibleOrders = computed(() =>
    (this.orders.value() ?? []).filter((o) => !o.archived),
  );
}

Subscription teardown without ceremony:

export class SearchComponent {
  private readonly destroyRef = inject(DestroyRef);

  constructor() {
    this.searchControl.valueChanges
      .pipe(
        debounceTime(300),
        distinctUntilChanged(),
        switchMap((q) => this.api.search(q)),   // cancels the in-flight request
        takeUntilDestroyed(this.destroyRef),    // unsubscribes on destroy
      )
      .subscribe((results) => this.results.set(results));
  }
}

Notes

  • The new control-flow syntax (@if, @for, @switch) is not sugar — it compiles to more efficient code than *ngIf and *ngFor, and track is mandatory in @for, which eliminates a whole class of list-diffing bugs.
  • OnPush with mutable objects will not update: it compares references. Either treat inputs as immutable or use signals, which notify explicitly.
  • A computed signal that reads another computed is fine and does not recompute unnecessarily — the graph is lazy and memoized.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.