Org Skills

angular-migration

Plan and execute Angular upgrades and modernisation — `ng update` one major at a time, NgModule to standalone, `*ngIf`/`*ngFor` to built-in control flow, constructor DI to `inject()`, decorators to signal inputs, outputs and queries, eager to lazy routes, `CommonModule` and `ngClass`/`ngStyle` removal, zone.js to zoneless, Karma to Vitest, `@angular/animations` to `animate.enter`/`animate.leave`, and Reactive Forms to Signal Forms.

Download .zip Raw Source
When agents use itUse this whenever the user is on Angular 19 or older, asks how to upgrade Angular or "modernise" an Angular codebase, mentions `ng update`, a migration schematic, `ng generate @angular/core:…`, a breaking change after an upgrade, removing zone.js, or getting off Karma, `RouterTestingModule` or `TestBed.flushEffects()`. Also use it when a new-feature request turns out to be blocked by an unsupported Angular version.

Install

Copilot (VS Code, Visual Studio, Copilot CLI and github.com) reads skills from the repository — commit them so the whole team gets them.

npx skills add AGCO-Global/org-skills --skill angular-migration -a github-copilot
# or with the org installer (adds .github/skills/angular-migration):
npx -y github:AGCO-Global/org-skills add skill angular-migration

Uses the open skills CLI. Works with Claude Code, Codex, Cursor, Copilot, Gemini CLI, OpenCode, Windsurf and 60+ others — it asks which agent to install into.

npx skills add AGCO-Global/org-skills --skill angular-migration
# user-level instead of project-level:
npx skills add AGCO-Global/org-skills --skill angular-migration -g

Installs the frontend-angular-skills plugin, which bundles all Frontend / Angular skills and keeps them updated.

/plugin marketplace add AGCO-Global/org-skills
/plugin install frontend-angular-skills@org-skills
# or just this skill, in this repository:
npx skills add AGCO-Global/org-skills --skill angular-migration -a claude-code

Use Download .zip above, then upload it under Customize → Skills → Upload skill. Team and Enterprise admins can sync this repo as a plugin marketplace instead.

Installs into .agents/skills/, which Codex reads.

npx skills add AGCO-Global/org-skills --skill angular-migration -a codex

Installs into Cursor's skills folder.

npx skills add AGCO-Global/org-skills --skill angular-migration -a cursor

Installs into Gemini CLI's skills folder.

npx skills add AGCO-Global/org-skills --skill angular-migration -a gemini-cli

Any tool with rules, instructions or custom prompts: use Copy SKILL.md above and paste it in. It is plain Markdown.

Commands use your normal git sign-in to GitHub, so they work while the repository is private. Node.js 20+ required.

Try it — example prompts

Prompts this skill is tested against, and what a good answer includes.

  • Give me the exact commands to migrate our Angular 16 NgModule app to standalone + signals.

    ng update one major at a time up to a supported version first ng generate @angular/core:standalone run in its three modes in order ng generate @angular/core:control-flow ng generate @angular/core:inject ng generate @angular/core:signal-input-migration ng generate @angular/core:output-migration ng generate @angular/core:signal-queries-migration ng generate @angular/core:route-lazy-loading one PR per schematic with tests green between steps

  • We're on Angular 19. Is that fine to stay on for another year?

    v19 is out of support and receives no fixes including security fixes names v22 as Active and v21 and v20 as LTS with end dates upgrade plan is the first deliverable one major at a time via ng update

  • We removed zone.js and now our third-party datepicker doesn't update the view until I click elsewhere.

    explains that zone.js patching no longer triggers change detection lists what notifies Angular in zoneless mode (signal write, template or host listener, markForCheck, setInput) fix is to write a signal or call markForCheck in the widget callback does not recommend restoring zone.js

  • How do we get off @angular/animations? We use trigger/state/transition for a slide-in panel.

    @angular/animations is deprecated animate.enter and animate.leave with a CSS class class binding plus a CSS transition for state changes remove provideAnimations / provideNoopAnimations prefers-reduced-motion handled

  • Our Angular 22 build fails with 'afterRender is not exported from @angular/core'. What happened?

    afterRender was renamed afterEveryRender in v20 with no alias afterNextRender for a one-off phases are object keys, the AfterRenderPhase enum is gone shows the corrected call

Skill contents

Angular Migration

Targets: upgrades into Angular 20 LTS – 22 · Verified: 2026-09 against https://angular.dev/reference/releases, https://angular.dev/reference/migrations, https://angular.dev/update-guide

A migration succeeds when every step is small, mechanical and independently shippable, and CI is green after each one. Angular ships schematics for almost all of this work — running the schematic and reviewing its diff beats a hand-rewrite on both speed and accuracy. The failure mode is the "big modernisation branch" that is six weeks old, conflicts with everything and can never be merged.

1. Decide first

Question Default Change when
Upgrade or modernise first? Upgrade to a supported major first; modernisation schematics assume current APIs A v22 codebase already: skip to section 4
How many majors at once One at a time, ng update per major, commit and deploy between them Never batch. Skipping a major skips its migrations and its deprecation warnings
Order of modernisation Standalone → control flow → inject() → signal inputs/outputs/queries → lazy routes → cleanup A single blocker (a library with no standalone support) can reorder, but standalone gates most of the rest
Branch strategy One PR per schematic, straight to trunk, behind no flag A schematic touching > 300 files → split with --path per feature folder
Test suite during the move Keep Karma running until the app is on v21+ and standalone The suite is already the bottleneck → move to Vitest first, it is independent of the rest
Hand edits after a schematic Review the diff, fix what it flagged, commit as one change Never hand-edit the same file the next schematic will rewrite
Below v20 The upgrade plan is the deliverable, before any feature work Only a hotfix is in scope

Version status as of 2026-09: v22 Active (released 2026-06-03, LTS ends 2028-06), v21 LTS (ends 2027-06), v20 LTS (ends 2026-11-28). v19 and below get no fixes, including security fixes.

2. Upgrading majors

ng update                                  # shows what is available for this workspace
ng update @angular/core@21 @angular/cli@21 # one major, core and cli together
npm run test && npm run build              # green before the next major
  • ng update runs that major's own migrations automatically. That is why skipping majors is expensive: the migrations do not run retroactively.
  • Check https://angular.dev/update-guide for each hop with your exact from/to versions before starting; it lists the manual steps a schematic cannot do.
  • Third-party packages (@angular/material, @ngrx/*, @angular/cdk) are updated in the same command as the core hop they support, not after.
  • A library with no release for the target major is a decision, not a blocker to discover in week three: replace it, fork it, or stay one major back — but decide before the first ng update.
  • Commit each major separately. A bisect across a combined 19→22 commit tells you nothing.

3. What changed per version

Per-version defaults — zoneless (v21), OnPush (v22), Vitest (v21), Signal Forms, resource/httpResource and Angular Aria (v22), incremental hydration by default (v22) — are tabulated in version-notes.md in ../angular-development/references/. Read it before generating any code for a mixed-version repo.

The API changes most likely to break a build or mislead a generated fix: afterRender was renamed afterEveryRender in v20 with no alias; TestBed.flushEffects() is deprecated in favour of TestBed.tick(); withIncrementalHydration() is deprecated (incremental hydration is on by default in provideClientHydration()) and it enables event replay, so withEventReplay() should be dropped; @angular/animations is deprecated; ChangeDetectionStrategy.Default is deprecated in favour of Eager.

4. The modernisation schematics, in order

Run one, review the diff, run the tests, commit. Every command takes --path <dir> to scope it to one feature folder.

ng generate @angular/core:standalone                   # 3 modes, in this order:
#   1 convert components/directives/pipes to standalone
#   2 remove unnecessary NgModule classes
#   3 bootstrap with standalone APIs
ng generate @angular/core:control-flow                 # *ngIf/*ngFor/*ngSwitch → @if/@for/@switch
ng generate @angular/core:inject                       # constructor DI → inject()
ng generate @angular/core:signal-input-migration       # @Input → input()
ng generate @angular/core:output-migration             # @Output → output()
ng generate @angular/core:signal-queries-migration     # @ViewChild/@ContentChild → viewChild()/contentChild()
ng generate @angular/core:route-lazy-loading           # eager route components → loadComponent
ng generate @angular/core:common-to-standalone         # CommonModule → the directives/pipes actually used
ng generate @angular/core:ngclass-to-class             # ngClass → [class] bindings
ng generate @angular/core:ngstyle-to-style             # ngStyle → [style] bindings
ng generate @angular/core:cleanup-unused-imports       # drop imports the template no longer uses
ng generate @angular/core:self-closing-tag             # <x></x> → <x />
ng generate @angular/core:router-testing-module-migration  # RouterTestingModule → RouterModule + provideLocationMocks()

Note the singular in self-closing-tag, and that the inject() schematic is :inject:inject-migration does not exist.

:inject takes --migrate-abstract-classes (off by default, because Angular does not validate abstract-class parameters), --backwards-compatible-constructors and --non-null-assertion. :ngstyle-to-style has --best-effort-mode for object-reference bindings it would otherwise skip as unsafe.

Review every diff. The schematics are conservative and correct on what they touch, but they leave the judgement calls: a converted component may now import more than it needs, and :control-flow cannot know that an *ngFor should have gained an @empty branch.

5. The moves with no schematic

Four migrations are manual. Each is independently shippable, and each has a decision rather than a mechanical rule — details and step-by-step recipes in references/manual-migrations.md.

  • zone.js → zoneless. Add provideZonelessChangeDetection() on v20, or confirm nothing provides provideZoneChangeDetection() on v21+, remove zone.js from polyfills, then fix what stops updating: anything relying on zone patching now needs a signal write, a template/host listener, markForCheck() or ComponentRef.setInput. NgZone.runOutsideAngular calls become no-ops and should be deleted.
  • Karma → Vitest. npm install --save-dev vitest jsdom, set the test builder to @angular/build:unit-test, then ng g @schematics/angular:refactor-jasmine-vitest to convert spec syntax. It does not install dependencies, change angular.json or delete karma.conf.js — you do those. fakeAsync/tick stop working once zone.js is gone; replace with fake timers or await fixture.whenStable().
  • @angular/animations → CSS. animate.enter="<class>" and animate.leave="<class>" in templates, ordinary class bindings for state transitions, CSS transitions and keyframes for the animation itself.
  • Reactive Forms → Signal Forms. Only on v22+, only for forms you are already changing, and never half a form at a time. Typed Reactive Forms are not deprecated; a working reactive form is not technical debt.

6. Deliverable format

## Current state — Angular version, support status, NgModule/standalone split, test runner, zone.js, blockers
## Sequence — numbered steps, each one PR, each with its command and how it is verified
## Per-step risk — what could break and what test covers it
## Manual work — what no schematic does, with the estimate
## Not doing — what is deliberately left alone, and why

Checklist

  • Current and target versions stated, with support status
  • Upgrade hops are one major at a time, each with its own commit and green CI
  • Every third-party Angular dependency checked for a release supporting the target major
  • The update guide consulted for each hop's manual steps
  • Schematic commands are exact (:inject, :self-closing-tag, :signal-input-migration) and scoped with --path where the diff would be huge
  • Each schematic is its own PR with a reviewed diff, not a batch
  • Removed APIs handled: afterRender, TestBed.flushEffects(), withIncrementalHydration(), withEventReplay(), @angular/animations
  • Zoneless step verified by clicking through, not just by a green unit suite
  • Nothing rewritten that works and is not deprecated (typed Reactive Forms, @Injectable, existing Jest suites)

Anti-patterns

  • One long-lived "modernisation" branch → one PR per schematic onto trunk; a six-week branch merges never.
  • Skipping majors ("19 straight to 22") → each ng update runs that major's migrations; skipping means doing them by hand, later, without the warnings.
  • Hand-rewriting what a schematic does → slower and less accurate; run it, review it, then hand-fix only what it flagged.
  • ng generate @angular/core:inject-migration → the schematic is @angular/core:inject.
  • Converting Reactive Forms to Signal Forms across the app → Reactive Forms are supported; convert only forms you are already rewriting, on v22+.
  • Removing zone.js while the suite still uses fakeAsync → move the tests first, or the suite fails for a reason unrelated to the app.
  • Keeping withEventReplay() and withIncrementalHydration() after v22 → both are redundant; incremental hydration is the default and enables event replay itself.
  • Mixing .component.ts and suffix-less names as the rename proceeds → do the rename as one mechanical PR, or not at all (see angular-architecture).

Go deeper

  • references/manual-migrations.md — zoneless, Karma → Vitest, animations → CSS, Reactive → Signal Forms, RouterTestingModule, step by step
  • references/upgrade-playbook.md — a worked 17 → 22 sequence with per-hop commands, checkpoints and rollback
  • version-notes.md in ../angular-development/references/ — what is default in v20, v21 and v22
  • Siblings: angular-architecture (target structure), angular-development (the modern idioms), angular-testing (the new suite), angular-ssr

References

Deeper material the agent loads only when needed.