Help us improve
Share bugs, ideas, or general feedback.
From ng
Migrate deprecated Angular patterns to modern equivalents. Auto-invoked when editing NgModule files or using deprecated APIs.
npx claudepluginhub mayeedwin/angular-plugin --plugin ngHow this skill is triggered — by the user, by Claude, or both
Slash command
/ng:angular-migrationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**Reference**: https://angular.dev/update-guide
Master AngularJS to Angular migration, covering hybrid apps, component conversion, dependency injection changes, and routing migration. Use for incremental or big-bang strategies with ngUpgrade.
Provides Angular 14+ expertise for standalone components, signals, RxJS patterns, NgRx state management, dependency injection, lazy loading routes, OnPush change detection, and testing.
Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Share bugs, ideas, or general feedback.
Reference: https://angular.dev/update-guide
When reading Angular files, flag these patterns for migration:
| Deprecated pattern | Modern replacement |
|---|---|
*.module.ts with declarations | Standalone components |
*ngIf, *ngFor, *ngSwitch | @if, @for, @switch |
constructor(private svc: Service) | inject(Service) |
ngOnDestroy + Subject + takeUntil | takeUntilDestroyed() |
Class-based CanActivate guard | CanActivateFn functional guard |
Class-based HttpInterceptor | HttpInterceptorFn functional interceptor |
APP_INITIALIZER + factory | provideAppInitializer(() => ...) |
RouterModule.forRoot() | provideRouter(routes) in app.config.ts |
HttpClientModule import | provideHttpClient() in app.config.ts |
BrowserModule import | Remove — not needed for standalone |
platformBrowserDynamic().bootstrapModule | bootstrapApplication(AppComponent, appConfig) |
Zone.js dependency only | Consider zoneless: provideExperimentalZonelessChangeDetection() |
When converting a module-based component:
standalone: true to @ComponentNgModule.imports entries to component's imports arrayNgModule.declarationsloadComponent instead of loadChildrenReplace all structural directives in templates:
<!-- Old → New -->
<div *ngIf="show">...</div>
→ @if (show) { <div>...</div> }
<div *ngIf="show; else other">...</div>
<ng-template #other>...</ng-template>
→ @if (show) { <div>...</div> } @else { ... }
<li *ngFor="let item of items; trackBy: trackById">...</li>
→ @for (item of items; track item.id) { <li>...</li> }
<div [ngSwitch]="status">
<span *ngSwitchCase="'active'">Active</span>
</div>
→ @switch (status) { @case ('active') { <span>Active</span> } }
After migrating control flow, remove CommonModule if it was only providing NgIf/NgFor.
app.config.ts Migration// Old: main.ts + AppModule
platformBrowserDynamic().bootstrapModule(AppModule);
// New: main.ts
bootstrapApplication(AppComponent, appConfig);
// New: app.config.ts
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient(withInterceptors([authInterceptor])),
provideAnimationsAsync(),
provideStore(),
provideEffects(),
],
};
// Old
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private auth: AuthService, private router: Router) {}
canActivate(): boolean {
return this.auth.isLoggedIn() || (this.router.navigate(['/login']), false);
}
}
// New
export const authGuard: CanActivateFn = () => {
return inject(AuthService).isLoggedIn() || inject(Router).createUrlTree(['/login']);
};
DestroyRef, takeUntilDestroyed@if/@for/@switch stable, @defer stableAlways check package.json Angular version before suggesting a migration — don't suggest APIs unavailable in the project's version.