{
  "schema": "https://ai-atoms.com/schemas/skill-v1.json",
  "type": "skill",
  "id": "skill/angular-migration",
  "version": "1.0.0",
  "name": "Angular Migration",
  "description": "Migrate from AngularJS to Angular using hybrid mode, incremental component rewriting, and dependency injection updates. Use when upgrading AngularJS applications, planning framework migrations, or ...",
  "system_prompt_fragment": "# Angular Migration\n\nMaster AngularJS to Angular migration, including hybrid apps, component conversion, dependency injection changes, and routing migration.\n\n## Use this skill when\n\n- Migrating AngularJS (1.x) applications to Angular (2+)\n- Running hybrid AngularJS/Angular applications\n- Converting directives to components\n- Modernizing dependency injection\n- Migrating routing systems\n- Updating to latest Angular versions\n- Implementing Angular best practices\n\n## Do not use this skill when\n\n- You are not migrating from AngularJS to Angular\n- The app is already on a modern Angular version\n- You need only a small UI fix without framework changes\n\n## Instructions\n\n1. Assess the AngularJS codebase, dependencies, and migration risks.\n2. Choose a migration strategy (hybrid vs rewrite) and define milestones.\n3. Set up ngUpgrade and migrate modules, components, and routing.\n4. Validate with tests and plan a safe cutover.\n\n## Safety\n\n- Avoid big-bang cutovers without rollback and staging validation.\n- Keep hybrid compatibility testing during incremental migration.\n\n## Migration Strategies\n\n### 1. Big Bang (Complete Rewrite)\n- Rewrite entire app in Angular\n- Parallel development\n- Switch over at once\n- **Best for:** Small apps, green field projects\n\n### 2. Incremental (Hybrid Approach)\n- Run AngularJS and Angular side-by-side\n- Migrate feature by feature\n- ngUpgrade for interop\n- **Best for:** Large apps, continuous delivery\n\n### 3. Vertical Slice\n- Migrate one feature completely\n- New features in Angular, maintain old in AngularJS\n- Gradually replace\n- **Best for:** Medium apps, distinct features\n\n## Hybrid App Setup\n\n```typescript\n// main.ts - Bootstrap hybrid app\nimport { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\nimport { UpgradeModule } from '@angular/upgrade/static';\nimport { AppModule } from './app/app.module';\n\nplatformBrowserDynamic()\n  .bootstrapModule(AppModule)\n  .then(platformRef => {\n    const upgrade = platformRef.injector.get(UpgradeModule);\n    // Bootstrap AngularJS\n    upgrade.bootstrap(document.body, ['myAngularJSApp'], { strictDi: true });\n  });\n```\n\n```typescript\n// app.module.ts\nimport { NgModule } from '@angular/core';\nimport { BrowserModule } from '@angular/platform-browser';\nimport { UpgradeModule } from '@angular/upgrade/static';\n\n@NgModule({\n  imports: [\n    BrowserModule,\n    UpgradeModule\n  ]\n})\nexport class AppModule {\n  constructor(private upgrade: UpgradeModule) {}\n\n  ngDoBootstrap() {\n    // Bootstrapped manually in main.ts\n  }\n}\n```\n\n## Component Migration\n\n### AngularJS Controller → Angular Component\n```javascript\n// Before: AngularJS controller\nangular.module('myApp').controller('UserController', function($scope, UserService) {\n  $scope.user = {};\n\n  $scope.loadUser = function(id) {\n    UserService.getUser(id).then(function(user) {\n      $scope.user = user;\n    });\n  };\n\n  $scope.saveUser = function() {\n    UserService.saveUser($scope.user);\n  };\n});\n```\n\n```typescript\n// After: Angular component\nimport { Component, OnInit } from '@angular/core';\nimport { UserService } from './user.service';\n\n@Component({\n  selector: 'app-user',\n  template: `\n    <div>\n      <h2>{{ user.name }}</h2>\n      <button (click)=\"saveUser()\">Save</button>\n    </div>\n  `\n})\nexport class UserComponent implements OnInit {\n  user: any = {};\n\n  constructor(private userService: UserService) {}\n\n  ngOnInit() {\n    this.loadUser(1);\n  }\n\n  loadUser(id: number) {\n    this.userService.getUser(id).subscribe(user => {\n      this.user = user;\n    });\n  }\n\n  saveUser() {\n    this.userService.saveUser(this.user);\n  }\n}\n```\n\n### AngularJS Directive → Angular Component\n```javascript\n// Before: AngularJS directive\nangular.module('myApp').directive('userCard', function() {\n  return {\n    restrict: 'E',\n    scope: {\n      user: '=',\n      onDelete: '&'\n    },\n    template: `\n      <div class=\"card\">\n        <h3>{{ user.name }}</h3>\n        <button ng-click=\"onDelete()\">Delete</button>\n      </div>\n    `\n  };\n});\n```\n\n```typescript\n// After: Angular component\nimport { Component, Input, Output, EventEmitter } from '@angular/core';\n\n@Component({\n  selector: 'app-user-card',\n  template: `\n    <div class=\"card\">\n      <h3>{{ user.name }}</h3>\n      <button (click)=\"delete.emit()\">Delete</button>\n    </div>\n  `\n})\nexport class UserCardComponent {\n  @Input() user: any;\n  @Output() delete = new EventEmitter<void>();\n}\n\n// Usage: <app-user-card [user]=\"user\" (delete)=\"handleDelete()\"></app-user-card>\n```\n\n## Service Migration\n\n```javascript\n// Before: AngularJS service\nangular.module('myApp').factory('UserService', function($http) {\n  return {\n    getUser: function(id) {\n      return $http.get('/api/users/' + id);\n    },\n    saveUser: function(user) {\n      return $http.post('/api/users', user);\n    }\n  };\n});\n```\n\n```typescript\n// After: Angular service\nimport { Injectable } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\nimport { Observable } from 'rxjs';\n\n@Injectable({\n  providedIn: 'root'\n})\nexport class UserService {\n  constructor(private http: HttpClient) {}\n\n  getUser(id: number): Observable<any> {\n    return this.http.get(`/api/users/${id}`);\n  }\n\n  saveUser(user: any): Observable<any> {\n    return this.http.post('/api/users', user);\n  }\n}\n```\n\n## Dependency Injection Changes\n\n### Downgrading Angular → AngularJS\n```typescript\n// Angular service\nimport { Injectable } from '@angular/core';\n\n@Injectable({ providedIn: 'root' })\nexport class NewService {\n  getData() {\n    return 'data from Angular';\n  }\n}\n\n// Make available to AngularJS\nimport { downgradeInjectable } from '@angular/upgrade/static';\n\nangular.module('myApp')\n  .factory('newService', downgradeInjectable(NewService));\n\n// Use in AngularJS\nangular.module('myApp').controller('OldController', function(newService) {\n  console.log(newService.getData());\n});\n```\n\n### Upgrading AngularJS → Angular\n```typescript\n// AngularJS service\nangular.module('myApp').factory('oldService', function() {\n  return {\n    getData: function() {\n      return 'data from AngularJS';\n    }\n  };\n});\n\n// Make available to Angular\nimport { InjectionToken } from '@angular/core';\n\nexport const OLD_SERVICE = new InjectionToken<any>('oldService');\n\n@NgModule({\n  providers: [\n    {\n      provide: OLD_SERVICE,\n      useFactory: (i: any) => i.get('oldService'),\n      deps: ['$injector']\n    }\n  ]\n})\n\n// Use in Angular\n@Component({...})\nexport class NewComponent {\n  constructor(@Inject(OLD_SERVICE) private oldService: any) {\n    console.log(this.oldService.getData());\n  }\n}\n```\n\n## Routing Migration\n\n```javascript\n// Before: AngularJS routing\nangular.module('myApp').config(function($routeProvider) {\n  $routeProvider\n    .when('/users', {\n      template: '<user-list></user-list>'\n    })\n    .when('/users/:id', {\n      template: '<user-detail></user-detail>'\n    });\n});\n```\n\n```typescript\n// After: Angular routing\nimport { NgModule } from '@angular/core';\nimport { RouterModule, Routes } from '@angular/router';\n\nconst routes: Routes = [\n  { path: 'users', component: UserListComponent },\n  { path: 'users/:id', component: UserDetailComponent }\n];\n\n@NgModule({\n  imports: [RouterModule.forRoot(routes)],\n  exports: [RouterModule]\n})\nexport class AppRoutingModule {}\n```\n\n## Forms Migration\n\n```html\n<!-- Before: AngularJS -->\n<form name=\"userForm\" ng-submit=\"saveUser()\">\n  <input type=\"text\" ng-model=\"user.name\" required>\n  <input type=\"email\" ng-model=\"user.email\" required>\n  <button ng-disabled=\"userForm.$invalid\">Save</button>\n</form>\n```\n\n```typescript\n// After: Angular (Template-driven)\n@Component({\n  template: `\n    <form #userForm=\"ngForm\" (ngSubmit)=\"saveUser()\">\n      <input type=\"text\" [(ngModel)]=\"user.name\" name=\"name\" required>\n      <input type=\"email\" [(ngModel)]=\"user.email\" name=\"email\" required>\n      <button [disabled]=\"userForm.invalid\">Save</button>\n    </form>\n  `\n})\n\n// Or Reactive Forms (preferred)\nimport { FormBuilder, FormGroup, Validators } from '@angular/forms';\n\n@Component({\n  template: `\n    <form [formGroup]=\"userForm\" (ngSubmit)=\"saveUser()\">\n      <input formControlName=\"name\">\n      <input formControlName=\"email\">\n      <button [disabled]=\"userForm.invalid\">Save</button>\n    </form>\n  `\n})\nexport class UserFormComponent {\n  userForm: FormGroup;\n\n  constructor(private fb: FormBuilder) {\n    this.userForm = this.fb.group({\n      name: ['', Validators.required],\n      email: ['', [Validators.required, Validators.email]]\n    });\n  }\n\n  saveUser() {\n    console.log(this.userForm.value);\n  }\n}\n```\n\n## Migration Timeline\n\n```\nPhase 1: Setup (1-2 weeks)\n- Install Angular CLI\n- Set up hybrid app\n- Configure build tools\n- Set up testing\n\nPhase 2: Infrastructure (2-4 weeks)\n- Migrate services\n- Migrate utilities\n- Set up routing\n- Migrate shared components\n\nPhase 3: Feature Migration (varies)\n- Migrate feature by feature\n- Test thoroughly\n- Deploy incrementally\n\nPhase 4: Cleanup (1-2 weeks)\n- Remove AngularJS code\n- Remove ngUpgrade\n- Optimize bundle\n- Final testing\n```\n\n## Resources\n\n- **references/hybrid-mode.md**: Hybrid app patterns\n- **references/component-migration.md**: Component conversion guide\n- **references/dependency-injection.md**: DI migration strategies\n- **references/routing.md**: Routing migration\n- **assets/hybrid-bootstrap.ts**: Hybrid app template\n- **assets/migration-timeline.md**: Project planning\n- **scripts/analyze-angular-app.sh**: App analysis script\n\n## Best Practices\n\n1. **Start with Services**: Migrate services first (easier)\n2. **Incremental Approach**: Feature-by-feature migration\n3. **Test Continuously**: Test at every step\n4. **Use TypeScript**: Migrate to TypeScript early\n5. **Follow Style Guide**: Angular style guide from day 1\n6. **Optimize Later**: Get it working, then optimize\n7. **Document**: Keep migration notes\n\n## Common Pitfalls\n\n- Not setting up hybrid app correctly\n- Migrating UI before logic\n- Ignoring change detection differences\n- Not handling scope properly\n- Mixing patterns (AngularJS + Angular)\n- Inadequate testing",
  "applicable_domains": [
    "frontend"
  ],
  "category": "frontend",
  "invocation": [
    "/angular-migration"
  ],
  "authored_by": "claudeskills.in community",
  "source_url": "https://claudeskills.in/skill/angular-migration",
  "provenance": {
    "source": "claudeskills.in",
    "source_url": "https://claudeskills.in/skill/angular-migration",
    "license": "unknown",
    "imported_at": "2026-09-03",
    "notes": "Aggregated by claudeskills.in from community GitHub lists."
  },
  "tags": [
    "claudeskills",
    "frontend"
  ],
  "lifecycle": "draft"
}