New to Claude Skills? Learn how to install them →

Asickn33 on GitHub

Angular Migration

Free

Seamlessly transition from AngularJS to Angular.

Get this skill

Free · Opens the source repo

What Angular Migration does

The Angular Migration skill provides comprehensive guidance for developers looking to migrate their applications from AngularJS (1.x) to Angular (2+). This skill is particularly useful for those managing hybrid applications, where both AngularJS and Angular coexist. It covers essential aspects of migration, including converting AngularJS directives to Angular components, modernizing dependency injection practices, and upgrading routing systems. By following the structured approach outlined in this skill, developers can ensure a smooth transition while adhering to Angular best practices.

This skill begins with assessing the existing AngularJS codebase, identifying dependencies, and evaluating migration risks. Users will learn to choose an appropriate migration strategy, whether it be a complete rewrite (Big Bang), an incremental approach (Hybrid), or a vertical slice method. Each strategy is tailored to fit different project sizes and requirements, allowing for flexibility in execution. The skill also emphasizes the importance of validation through testing and planning for a safe cutover, minimizing disruptions during the migration process.

Additionally, the skill provides practical code examples, illustrating how to convert AngularJS controllers and services into Angular components and services. It also addresses changes in dependency injection, ensuring that developers can effectively downgrade Angular services for use in AngularJS and upgrade AngularJS services to be utilized in Angular. This hands-on approach equips developers with the knowledge and tools necessary to modernize their applications efficiently.

When to use it

Use this skill when you are planning to migrate an AngularJS application to Angular, especially if you are dealing with hybrid applications or need to modernize your codebase.

When not to use it

This skill is not suitable if your application is already using a modern version of Angular or if you only require minor UI fixes without framework changes.

What you can build with it

Migrating a Large AngularJS Application

Use this skill to plan and execute the migration of a large AngularJS application to Angular using the incremental approach.

Converting Directives to Components

This skill provides the necessary steps and code examples for converting AngularJS directives into Angular components.

Modernizing Dependency Injection

Learn how to update your dependency injection practices during migration to ensure compatibility with Angular.

How to install Angular Migration

View source

1. Install with the skills CLI

npx skills add sickn33/agentic-awesome-skills/angular-migration --agent claude-code

2. Or install it manually

Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.

Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs

Inside SKILL.md

Written by sickn33

Angular Migration

Master AngularJS to Angular migration, including hybrid apps, component conversion, dependency injection changes, and routing migration.

Use this skill when

  • Migrating AngularJS (1.x) applications to Angular (2+)
  • Running hybrid AngularJS/Angular applications
  • Converting directives to components
  • Modernizing dependency injection
  • Migrating routing systems
  • Updating to latest Angular versions
  • Implementing Angular best practices

Do not use this skill when

  • You are not migrating from AngularJS to Angular
  • The app is already on a modern Angular version
  • You need only a small UI fix without framework changes

Instructions

  1. Assess the AngularJS codebase, dependencies, and migration risks.
  2. Choose a migration strategy (hybrid vs rewrite) and define milestones.
  3. Set up ngUpgrade and migrate modules, components, and routing.
  4. Validate with tests and plan a safe cutover.

Safety

  • Avoid big-bang cutovers without rollback and staging validation.
  • Keep hybrid compatibility testing during incremental migration.

Migration Strategies

1. Big Bang (Complete Rewrite)

  • Rewrite entire app in Angular
  • Parallel development
  • Switch over at once
  • Best for: Small apps, green field projects

2. Incremental (Hybrid Approach)

  • Run AngularJS and Angular side-by-side
  • Migrate feature by feature
  • ngUpgrade for interop
  • Best for: Large apps, continuous delivery

3. Vertical Slice

  • Migrate one feature completely
  • New features in Angular, maintain old in AngularJS
  • Gradually replace
  • Best for: Medium apps, distinct features

Hybrid App Setup

// main.ts - Bootstrap hybrid app
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { UpgradeModule } from '@angular/upgrade/static';
import { AppModule } from './app/app.module';

platformBrowserDynamic()
  .bootstrapModule(AppModule)
  .then(platformRef => {
    const upgrade = platformRef.injector.get(UpgradeModule);
    // Bootstrap AngularJS
    upgrade.bootstrap(document.body, ['myAngularJSApp'], { strictDi: true });
  });
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UpgradeModule } from '@angular/upgrade/static';

@NgModule({
  imports: [
    BrowserModule,
    UpgradeModule
  ]
})
export class AppModule {
  constructor(private upgrade: UpgradeModule) {}

  ngDoBootstrap() {
    // Bootstrapped manually in main.ts
  }
}

Component Migration

AngularJS Controller → Angular Component

// Before: AngularJS controller
angular.module('myApp').controller('UserController', function($scope, UserService) {
  $scope.user = {};

  $scope.loadUser = function(id) {
    UserService.getUser(id).then(function(user) {
      $scope.user = user;
    });
  };

  $scope.saveUser = function() {
    UserService.saveUser($scope.user);
  };
});
// After: Angular component
import { Component, OnInit } from '@angular/core';
import { UserService } from './user.service';

@Component({
  selector: 'app-user',
  template: `
    <div>
      <h2>{{ user.name }}</h2>
      <button (click)="saveUser()">Save</button>
    </div>
  `
})
export class UserComponent implements OnInit {
  user: any = {};

  constructor(private userService: UserService) {}

  ngOnInit() {
    this.loadUser(1);
  }

  loadUser(id: number) {
    this.userService.getUser(id).subscribe(user => {
      this.user = user;
    });
  }

  saveUser() {
    this.userService.saveUser(this.user);
  }
}

AngularJS Directive → Angular Component

// Before: AngularJS directive
angular.module('myApp').directive('userCard', function() {
  return {
    restrict: 'E',
    scope: {
      user: '=',
      onDelete: '&'
    },
    template: `
      <div class="card">
        <h3>{{ user.name }}</h3>
        <button ng-click="onDelete()">Delete</button>
      </div>
    `
  };
});
// After: Angular component
import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-user-card',
  template: `
    <div class="card">
      <h3>{{ user.name }}</h3>
      <button (click)="delete.emit()">Delete</button>
    </div>
  `
})
export class UserCardComponent {
  @Input() user: any;
  @Output() delete = new EventEmitter<void>();
}

// Usage: <app-user-card [user]="user" (delete)="handleDelete()"></app-user-card>

Service Migration

// Before: AngularJS service
angular.module('myApp').factory('UserService', function($http) {
  return {
    getUser: function(id) {
      return $http.get('/api/users/' + id);
    },
    saveUser: function(user) {
      return $http.post('/api/users', user);
    }
  };
});
// After: Angular service
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  constructor(private http: HttpClient) {}

  getUser(id: number): Observable<any> {
    return this.http.get(`/api/users/${id}`);
  }

  saveUser(user: any): Observable<any> {
    return this.http.post('/api/users', user);
  }
}

Dependency Injection Changes

Downgrading Angular → AngularJS

// Angular service
import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class NewService {
  getData() {
    return 'data from Angular';
  }
}

// Make available to AngularJS
import { downgradeInjectable } from '@angular/upgrade/static';

angular.module('myApp')
  .factory('newService', downgradeInjectable(NewService));

// Use in AngularJS
angular.module('myApp').controller('OldController', function(newService) {
  console.log(newService.getData());
});

Upgrading AngularJS → Angular

// AngularJS service
angular.module('myApp').factory('oldService', function() {
  return {
    getData: function() {
      return 'data from AngularJS';
    }
  };
});

// Make available to Angular
import { InjectionToken } from '@angular/core';

export const OLD_SERVICE = new InjectionToken<any>('oldService');

@NgModule({
  providers: [
    {
      provide: OLD_SERVICE,
      useFactory: (i: any) => i.get('oldService'),
      deps: ['$injector']
    }
  ]
})

// Use in Angular
@Component({...})
export class NewComponent {
  constructor(@Inject(OLD_SERVICE) private oldService: any) {
    console.log(this.oldService.getData());
  }
}

Routing Migration

// Before: AngularJS routing
angular.module('myApp').config(function($routeProvider) {
  $routeProvider
    .when('/users', {
      template: '<user-list></user-list>'
    })
    .when('/users/:id', {
      template: '<user-detail></user-detail>'
    });
});
// After: Angular routing
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  { path: 'users', component: UserListComponent },
  { path: 'users/:id', component: UserDetailComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {}

Forms Migration

<!-- Before: AngularJS -->
<form name="userForm" ng-submit="saveUser()">
  <input type="text" ng-model="user.name" required>
  <input type="email" ng-model="user.email" required>
  <button ng-disabled="userForm.$invalid">Save</button>
</form>
// After: Angular (Template-driven)
@Component({
  template: `
    <form #userForm="ngForm" (ngSubmit)="saveUser()">
      <input type="text" [(ngModel)]="user.name" name="name" required>
      <input type="email" [(ngModel)]="user.email" name="email" required>
      <button [disabled]="userForm.invalid">Save</button>
    </form>
  `
})

// Or Reactive Forms (preferred)
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
  template: `
    <form [formGroup]="userForm" (ngSubmit)="saveUser()">
      <input formControlName="name">
      <input formControlName="email">
      <button [disabled]="userForm.invalid">Save</button>
    </form>
  `
})
export class UserFormComponent {
  userForm: FormGroup;

  constructor(private fb: FormBuilder) {
    this.userForm = this.fb.group({
      name: ['', Validators.required],
      email: ['', [Validators.required, Validators.email]]
    });
  }

  saveUser() {
    console.log(this.userForm.value);
  }
}

Migration Timeline

Phase 1: Setup (1-2 weeks)
- Install Angular CLI
- Set up hybrid app
- Configure build tools
- Set up testing

Phase 2: Infrastructure (2-4 weeks)
- Migrate services
- Migrate utilities
- Set up routing
- Migrate shared components

Phase 3: Feature Migration (varies)
- Migrate feature by feature
- Test thoroughly
- Deploy incrementally

Phase 4: Cleanup (1-2 weeks)
- Remove AngularJS code
- Remove ngUpgrade
- Optimize bundle
- Final testing

Resources

  • references/hybrid-mode.md: Hybrid app patterns
  • references/component-migration.md: Component conversion guide
  • references/dependency-injection.md: DI migration strategies
  • references/routing.md: Routing migration
  • assets/hybrid-bootstrap.ts: Hybrid app template
  • assets/migration-timeline.md: Project planning
  • scripts/analyze-angular-app.sh: App analysis script

Best Practices

  1. Start with Services: Migrate services first (easier)
  2. Incremental Approach: Feature-by-feature migration
  3. Test Continuously: Test at every step
  4. Use TypeScript: Migrate to TypeScript early
  5. Follow Style Guide: Angular style guide from day 1
  6. Optimize Later: Get it working, then optimize
  7. Document: Keep migration notes

Common Pitfalls

  • Not setting up hybrid app correctly
  • Migrating UI before logic
  • Ignoring change detection differences
  • Not handling scope properly
  • Mixing patterns (AngularJS + Angular)
  • Inadequate testing

Limitations

  • Use this skill only when the task clearly matches the scope described above.
  • Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
  • Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.

Frequently asked questions about Angular Migration

Similar skills