Skip to main content

angular

Modern Angular (v20+) expert with deep knowledge of Signals, Standalone Components, Zoneless applications, SSR/Hydration, and reactive patterns.

Jump to install

Source facts

Repository
muhammedadnank/Antigravity-Skills
Last source activity
June 6, 2026 at 18:30
Detected SKILL.md language
English
Stars
13
Forks
1

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
3 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
angular
description
Modern Angular (v20+) expert with deep knowledge of Signals, Standalone Components, Zoneless applications, SSR/Hydration, and reactive patterns.
risk
safe
source
self
date_added
2026-02-27
# Angular Expert Master modern Angular development with Signals, Standalone Components, Zoneless applications, SSR/Hydration, and the latest reactive patterns. ## 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-migration` skill - Working with legacy Angular apps that cannot upgrade - General TypeScript issues → use `typescript-expert` skill ## Instructions 1. Assess the Angular version and project structure 2. Apply modern patterns (Signals, Standalone, Zoneless) 3. Implement with proper typing and reactivity 4. Validate with build and tests ## Safety - Always test changes in development before production - Gradual migration for existing apps (don't big-bang refactor) - Keep backward compatibility during transitions --- ## Angular Version Timeline | Version | Release | Key Features | | -------------- | ------- | ------------------------------------------------------ | | **Angular 20** | Q2 2025 | Signals stable, Zoneless stable, Incremental hydration | | **Angular 21** | Q4 2025 | Signals-first default, Enhanced SSR | | **Angular 22** | Q2 2026 | Signal Forms, Selectorless components | --- ## 1. Signals: The New Reactive Primitive Signals are Angular's fine-grained reactivity system, replacing zone.js-based change detection. ### Core Concepts ```typescript import { signal, computed, effect } from "@angular/core"; // Writable signal const count = signal(0); // Read value console.log(count()); // 0 // Update value count.set(5); // Direct set count.update((v) => v + 1); // Functional update // Computed (derived) signal const doubled = computed(() => count() * 2); // Effect (side effects) effect(() => { console.log(`Count changed to: ${count()}`); }); ``` ### Signal-Based Inputs and Outputs ```typescript import { Component, input, output, model } from "@angular/core"; @Component({ selector: "app-user-card", standalone: true, template: ` <div class="card"> <h3>{{ name() }}</h3> <span>{{ role() }}</span> <button (click)="select.emit(id())">Select</button> </div> `, }) export class UserCardComponent { // Signal inputs (read-only) id = input.required<string>(); name = input.required<string>(); role = input<string>("User"); // With default // Output select = output<string>(); // Two-way binding (model) isSelected = model(false); } // Usage: // <app-user-card [id]="'123'" [name]="'John'" [(isSelected)]="selected" /> ``` ### Signal Queries (ViewChild/ContentChild) ```typescript import { Component, viewChild, viewChildren, contentChild, } from "@angular/core"; @Component({ selector: "app-container", standalone: true, template: ` <input #searchInput /> <app-item *ngFor="let item of items()" /> `, }) export class ContainerComponent { // Signal-based queries searchInput = viewChild<ElementRef>("searchInput"); items = viewChildren(ItemComponent); projectedContent = contentChild(HeaderDirective); focusSearch() { this.searchInput()?.nativeElement.focus(); } } ``` ### When to Use Signals vs RxJS | Use Case | Signals | RxJS | | ----------------------- | --------------- | -------------------------------- | | Local component state | ✅ Preferred | Overkill | | Derived/computed values | ✅ `computed()` | `combineLatest` works | | Side effects | ✅ `effect()` | `tap` operator | | HTTP requests | ❌ | ✅ HttpClient returns Observable | | Event streams | ❌ | ✅ `fromEvent`, operators | | Complex async flows | ❌ | ✅ `switchMap`, `mergeMap` | --- ## 2. Standalone Components Standalone components are self-contained and don't require NgModule declarations. ### Creating Standalone Components ```typescript import { Component } from "@angular/core"; import { CommonModule } from "@angular/common"; import { RouterLink } from "@angular/router"; @Component({ selector: "app-header", standalone: true, imports: [CommonModule, RouterLink], // Direct imports template: ` <header> <a routerLink="/">Home</a> <a routerLink="/about">About</a> </header> `, }) export class HeaderComponent {} ``` ### Bootstrapping Without NgModule ```typescript // 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 ```typescript // app.routes.ts import { Routes } from "@angular/router"; 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 Zoneless applications don't use zone.js, improving performance and debugging. ### Enabling Zoneless Mode ```typescript // main.ts import { bootstrapApplication } from "@angular/platform-browser"; import { provideZonelessChangeDetection } from "@angular/core"; import { AppComponent } from "./app/app.component"; bootstrapApplication(AppComponent, { providers: [provideZonelessChangeDetection()], }); ``` ### Zoneless Component Patterns ```typescript import { Component, signal, ChangeDetectionStrategy } from "@angular/core"; @Component({ selector: "app-counter", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: ` <div>Count: {{ count() }}</div> <button (click)="increment()">+</button> `, }) export class CounterComponent { count = signal(0); increment() { this.count.update((v) => v + 1); // No zone.js needed - Signal triggers change detection } } ``` ### Key Zoneless Benefits - **Performance**: No zone.js patches on async APIs - **Debugging**: Clean stack traces without zone wrappers - **Bundle size**: Smaller without zone.js (~15KB savings) - **Interoperability**: Better with Web Components and micro-frontends --- ## 4. Server-Side Rendering & Hydration ### SSR Setup with Angular CLI ```bash ng add @angular/ssr ``` ### Hydration Configuration ```typescript // app.config.ts import { ApplicationConfig } from "@angular/core"; import { provideClientHydration, withEventReplay, } from "@angular/platform-browser"; export const appConfig: ApplicationConfig = { providers: [provideClientHydration(withEventReplay())], }; ``` ### Incremental Hydration (v20+) ```typescript import { Component } from "@angular/core"; @Component({ selector: "app-page", standalone: true, template: ` <app-hero /> @defer (hydrate on viewport) { <app-comments /> } @defer (hydrate on interaction) { <app-chat-widget /> } `, }) export class PageComponent {} ``` ### Hydration Triggers | Trigger | When to Use | | ---------------- | --------------------------------------- | | `on idle` | Low-priority, hydrate when browser idle | | `on viewport` | Hydrate when element enters viewport | | `on interaction` | Hydrate on first user interaction | | `on hover` | Hydrate when user hovers | | `on timer(ms)` | Hydrate after specified delay | --- ## 5. Modern Routing Patterns ### Functional Route Guards ```typescript // auth.guard.ts import { inject } from "@angular/core"; import { Router, CanActivateFn } from "@angular/router"; import { AuthService } from "./auth.service"; export const authGuard: CanActivateFn = (route, state) => { const auth = inject(AuthService); const router = inject(Router); if (auth.isAuthenticated()) { return true; } return router.createUrlTree(["/login"], { queryParams: { returnUrl: state.url }, }); }; // Usage in routes export const routes: Routes = [ { path: "dashboard", loadComponent: () => import("./dashboard.component"), canActivate: [authGuard], }, ]; ``` ### Route-Level Data Resolvers ```typescript import { inject } from '@angular/core'; import { ResolveFn } from '@angular/router'; import { UserService } from './user.service'; import { User } from './user.model'; export const userResolver: ResolveFn<User> = (route) => { const userService = inject(UserService); return userService.getUser(route.paramMap.get('id')!); }; // In routes { path: 'user/:id', loadComponent: () => import('./user.component'), resolve: { user: userResolver } } // In component export class UserComponent { private route = inject(ActivatedRoute); user = toSignal(this.route.data.pipe(map(d => d['user']))); } ``` --- ## 6. Dependency Injection Patterns ### Modern inject() Function ```typescript import { Component, inject } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { UserService } from './user.service'; @Component({...}) export class UserComponent { // Modern inject() - no constructor needed private http = inject(HttpClient); private userService = inject(UserService); // Works in any injection context users = toSignal(this.userService.getUsers()); } ``` ### Injection Tokens for Configuration
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub