Install
$ agentstack add skill-kumaran-is-claude-code-onboarding-angular ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Iron Law
READ angular-spa skill for TailwindCSS 4.x, daisyUI 5.5.5, and workspace conventions BEFORE implementing. This skill is API reference only — no design token or styling patterns here.
When to Use This Skill
- Building new Angular applications (v20+)
- Implementing Signals-based reactive patterns
- Creating Standalone Components and migrating from NgModules
- Configuring Zoneless Angular applications
- Implementing SSR, prerendering, and hydration
- Optimizing Angular performance
- Adopting modern Angular patterns and best practices
Do Not Use This Skill When
- Migrating from AngularJS (1.x) — use
angular-migrationskill - Working with legacy Angular apps that cannot upgrade
- General TypeScript issues — use
typescript-expertskill
Version context: Angular 20 (Signals/Zoneless stable), Angular 21 (Signals-first default, Signal Forms available — current), Angular 22 (Signal Forms further enhancements).
Angular 21 Zoneless Note
Angular 21 is zoneless by default. Do NOT add provideZonelessChangeDetection() — it is implicit and adding it causes warnings.
- Angular 20:
provideZonelessChangeDetection()required explicitly - Angular 21+: Zoneless is the default. No provider needed. No
zone.jsimport.
This workspace uses Angular 21+. The patterns below show v20-style explicit providers for reference — in Angular 21 omit those providers.
1. Signals: The New Reactive Primitive
Signals are Angular's fine-grained reactivity system, replacing zone.js-based change detection.
Core signal / computed / effect
import { signal, computed, effect } from "@angular/core";
const count = signal(0);
count.set(5);
count.update((v) => v + 1);
const doubled = computed(() => count() * 2);
effect(() => {
console.log(`Count changed to: ${count()}`);
});
Signal inputs, outputs, and model
import { Component, input, output, model } from "@angular/core";
@Component({
selector: "app-user-card",
standalone: true,
template: `
{{ name() }}
{{ role() }}
Select
`,
})
export class UserCardComponent {
id = input.required();
name = input.required();
role = input("User");
select = output();
isSelected = model(false);
}
//
Signal queries (viewChild, viewChildren, contentChild): See [references/signals-core.md](references/signals-core.md)
1b. linkedSignal — Derived Writable Signals
linkedSignal creates a writable signal whose default resets when its source changes.
| Use | Tool | |-----|------| | Derived read-only value | computed() | | Writable value that resets on source change | linkedSignal() | | Local state with no dependency | signal() |
import { signal, linkedSignal } from '@angular/core';
const items = signal(['a', 'b', 'c']);
const selectedItem = linkedSignal(() => items()[0]);
selectedItem.set('b'); // 'b'
items.set(['x', 'y', 'z']); // selectedItem resets to 'x'
Full examples (advanced + pagination): [references/signals-core.md](references/signals-core.md)
1c. resource() — Reactive Async Data Fetching
resource() is Angular's built-in reactive primitive for async data.
| Scenario | Use | |----------|-----| | Component-local async data tied to signals | resource() | | Service-level shared HTTP calls | HttpClient + inject() | | Complex async pipelines (retry, cancel, merge) | HttpClient + RxJS | | One-time data loads | Either |
import { httpResource } from '@angular/common/http';
// HTTP GET shorthand — refetches when userId() changes
userResource = httpResource(() => `/api/users/${this.userId()}`);
Full API (resource() component, abort signal, status signals): [references/signals-core.md](references/signals-core.md)
1d. afterNextRender / afterRender — DOM Lifecycle Hooks
In zoneless Angular 21, afterNextRender and afterRender replace NgZone lifecycle hacks for DOM-dependent initialization. Use these instead of ngAfterViewInit for code that requires a real DOM (chart init, third-party widget, scroll position).
import { Component, afterNextRender, afterRender, ElementRef, viewChild } from '@angular/core';
@Component({ selector: 'app-chart', template: '' })
export class ChartComponent {
canvas = viewChild.required>('canvas');
constructor() {
// Runs once after the first render — DOM is guaranteed to exist
afterNextRender(() => {
initChart(this.canvas().nativeElement);
});
// Runs after every render — use sparingly (performance cost)
afterRender(() => {
updateScrollPosition();
});
}
}
Rule: Prefer afterNextRender over afterRender — it runs once. Both run in the browser only (SSR-safe).
1e. @let — Template Variable Declaration (Angular 18+)
@let declares a local template variable — replaces the *ngIf as alias hack and verbose ng-template patterns.
@let user = currentUser();
@let greeting = 'Hello, ' + user.name + '!';
{{ greeting }}
{{ user.email }}
@let data = userResource.value();
@if (data) {
}
Rule: Use @let to avoid repeating computed signal calls in templates. Do not use it as a substitute for computed() — @let re-evaluates on every render pass.
1f. Testing: Vitest (Stable in Angular 21)
Angular 21 ships with Vitest as the stable test runner (replaces Karma). New projects default to Vitest. Migrate existing Karma setups.
// vitest.config.ts (Angular CLI generates this)
import { defineConfig } from 'vitest/config';
import angular from '@analogjs/vite-plugin-angular';
export default defineConfig({
plugins: [angular()],
test: {
globals: true,
environment: 'jsdom',
setupFiles: ['src/test-setup.ts'],
},
});
// Component test with zoneless TestBed
import { TestBed } from '@angular/core/testing';
import { provideExperimentalZonelessChangeDetection } from '@angular/core';
beforeEach(() => {
TestBed.configureTestingModule({
providers: [provideExperimentalZonelessChangeDetection()],
imports: [MyComponent],
});
});
Run: ng test (uses Vitest by default in Angular 21 workspaces). See reference/testing-vitest.md for full patterns.
2. Standalone Components
Standalone components are self-contained and don't require NgModule declarations.
Creating Standalone Components
import { Component } from "@angular/core";
import { CommonModule } from "@angular/common";
import { RouterLink } from "@angular/router";
@Component({
// standalone: true is the default in Angular v20+ — omit it
selector: "app-header",
imports: [RouterLink], // CommonModule is a compat shim — don't import it
template: `
Home
About
`,
})
export class HeaderComponent {}
Bootstrapping Without NgModule
// main.ts
import { bootstrapApplication } from "@angular/platform-browser";
import { provideRouter } from "@angular/router";
import { provideHttpClient } from "@angular/common/http";
import { AppComponent } from "./app/app.component";
import { routes } from "./app/app.routes";
bootstrapApplication(AppComponent, {
providers: [provideRouter(routes), provideHttpClient()],
});
Lazy Loading Standalone Components
export const routes: Routes = [
{
path: "dashboard",
loadComponent: () =>
import("./dashboard/dashboard.component").then((m) => m.DashboardComponent),
},
{
path: "admin",
loadChildren: () =>
import("./admin/admin.routes").then((m) => m.ADMIN_ROUTES),
},
];
3. Zoneless Angular
> Angular 21 reminder: Zoneless is the default. The provideZonelessChangeDetection() call below is v20-style — omit it in Angular 21 projects.
// main.ts (Angular 20 style — NOT needed in Angular 21+)
bootstrapApplication(AppComponent, {
providers: [provideZonelessChangeDetection()],
});
Zoneless Component Pattern
import { Component, signal, ChangeDetectionStrategy } from "@angular/core";
@Component({
selector: "app-counter",
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
Count: {{ count() }}
+
`,
})
export class CounterComponent {
count = signal(0);
increment() { this.count.update((v) => v + 1); }
}
Benefits: no zone.js patches, cleaner stack traces, ~15KB bundle savings, better Web Component interop.
4. Server-Side Rendering & Hydration
See [references/ssr-hydration.md](references/ssr-hydration.md) for SSR setup, hydration configuration, incremental hydration patterns, TransferState, and common SSR troubleshooting.
5. Modern Routing Patterns
> See [references/api-reference.md](references/api-reference.md) for full routing examples (functional guards, resolvers).
Key patterns:
CanActivateFnwithinject()for functional guardsResolveFnfor route-level data pre-fetchingtoSignal(route.data.pipe(...))to consume resolved data
6. Dependency Injection
> See [references/api-reference.md](references/api-reference.md) for full DI examples (inject(), InjectionToken).
Key patterns:
inject()function (no constructor required)InjectionTokenfor typed configuration values
7. Component Composition
> See [references/api-reference.md](references/api-reference.md) for full composition examples (ng-content slots, hostDirectives).
Key patterns:
- `` for named slots
hostDirectivesfor behavior composition without inheritance
8. Signal-Based State Management
> See [references/api-reference.md](references/api-reference.md) for full state service and component store examples.
Key patterns:
- Private
signal()+ publiccomputed()for encapsulated state @Injectable()(noprovidedIn: 'root') for scoped component stores
9. Forms with Signals
> See [references/api-reference.md](references/api-reference.md) for full reactive forms and signal form patterns.
Key patterns:
- Signal Forms (preferred for Angular 21+) — see
signal-forms.mdreference below FormBuilder+Validatorsfor reactive forms (legacy, still supported)- Signal-based validation via
computed()for derived validation state
> Angular 21+: Prefer Signal Forms over reactive forms for new apps. See [references/signal-forms.md](references/signal-forms.md).
10. Performance Optimization
Change Detection Strategies
Always use ChangeDetectionStrategy.OnPush. Triggers re-check only when: input signal/reference changes, event handler runs, async pipe emits, or signal value changes.
Defer Blocks for Lazy Loading
@defer (on viewport) {
} @placeholder {
} @loading (minimum 200ms) {
} @error {
Failed to load chart
}
NgOptimizedImage
import { NgOptimizedImage } from '@angular/common';
@Component({
imports: [NgOptimizedImage],
template: `
`
})
11. Testing Modern Angular
> See [references/api-reference.md](references/api-reference.md) for full testing examples (signal components, setInput).
Key patterns:
- Import standalone components directly in
TestBed.configureTestingModule({ imports: [...] }) - Use
componentRef.setInput('name', value)to set signal inputs in tests - Call
fixture.detectChanges()after signal mutations to trigger DOM update
Key Decision Tables
> See [references/api-reference.md](references/api-reference.md) for full Signals vs RxJS table and Pattern Do/Don't summary.
| Use Case | Use Signals | Use RxJS | | --------------------- | ------------ | ----------------------------- | | Local component state | Yes | No — overkill | | HTTP requests | No | Yes — HttpClient Observable | | Complex async flows | No | Yes — switchMap, mergeMap |
Common Troubleshooting
> See [references/api-reference.md](references/api-reference.md) for the full troubleshooting table.
| Issue | Solution | | ------------------------------ | --------------------------------------------------- | | Signal not updating UI | Ensure OnPush + call signal as function count() | | provideZonelessChangeDetection warning in v21 | Remove call — zoneless is the default in v21+ | | SSR fetch fails | Use TransferState or withFetch() |
Related Skills
angular-spa— workspace skill with TailwindCSS 4.x, daisyUI 5.5.5, conventionsangular-best-practices— impact-prioritized rules (CRITICAL to LOW-MEDIUM)angular-ui-patterns— loading, error, empty state patterns
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: kumaran-is
- Source: kumaran-is/claude-code-onboarding
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.