Install in Claude Code
Copygit clone --depth 1 https://github.com/TerminalSkills/skills /tmp/angular && cp -r /tmp/angular/skills/angular ~/.claude/skills/angularThen start a new Claude Code session; the skill loads automatically.
Definition
SKILL.md
# Angular
Angular is an opinionated, full-featured frontend framework. It uses TypeScript, components with templates, dependency injection, RxJS for async data, and a CLI for scaffolding.
## Installation
```bash
# Create new Angular project
npm i -g @angular/cli
ng new my-app --routing --style=scss
cd my-app
ng serve
```
## Project Structure
```
# Angular project layout
src/app/
├── app.component.ts # Root component
├── app.config.ts # Application config
├── app.routes.ts # Route definitions
├── articles/
│ ├── article-list/ # List component
│ ├── article-detail/ # Detail component
│ ├── article.service.ts # Data service
│ └── article.model.ts # Interface/type
├── auth/
│ ├── auth.service.ts
│ ├── auth.guard.ts
│ └── auth.interceptor.ts
└── shared/
├── components/
└── pipes/
```
## Components (Standalone)
```typescript
// src/app/articles/article-list/article-list.component.ts — standalone component
import { Component, inject, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterLink } from '@angular/router';
import { ArticleService } from '../article.service';
import { Article } from '../article.model';
@Component({
selector: 'app-article-list',
standalone: true,
imports: [CommonModule, RouterLink],
template: `
<h1>Articles</h1>
@for (article of articles; track article.id) {
<article>
<h2><a [routerLink]="['/articles', article.slug]">{{ article.title }}</a></h2>
<p>{{ article.excerpt }}</p>
</article>
} @empty {
<p>No articles found.</p>
}
`,
})
export class ArticleListComponent implements OnInit {
private articleService = inject(ArticleService);
articles: Article[] = [];
ngOnInit() {
this.articleService.getAll().subscribe((data) => (this.articles = data));
}
}
```
## Signals (Modern Reactivity)
```typescript
// src/app/articles/article-list/article-list.component.ts — signals-based component
import { Component, signal, computed, inject, OnInit } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { ArticleService } from '../article.service';
@Component({
selector: 'app-article-list',
standalone: true,
template: `
<input (input)="search.set($any($event.target).value)" placeholder="Search..." />
<div>{{ filteredCount() }} articles found</div>
@for (article of filtered(); track article.id) {
<article><h2>{{ article.title }}</h2></article>
}
`,
})
export class ArticleListComponent {
private svc = inject(ArticleService);
articles = toSignal(this.svc.getAll(), { initialValue: [] });
search = signal('');
filtered = computed(() =>
this.articles().filter((a) => a.title.toLowerCase().includes(this.search().toLowerCase()))
);
filteredCount = computed(() => this.filtered().length);
}
```
## Services
```typescript
// src/app/articles/article.service.ts — injectable data service
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Article } from './article.model';
@Injectable({ providedIn: 'root' })
export class ArticleService {
private http = inject(HttpClient);
private baseUrl = '/api/articles';
getAll(): Observable<Article[]> {
return this.http.get<Article[]>(this.baseUrl);
}
getBySlug(slug: string): Observable<Article> {
return this.http.get<Article>(`${this.baseUrl}/${slug}`);
}
create(article: Partial<Article>): Observable<Article> {
return this.http.post<Article>(this.baseUrl, article);
}
}
```
## Routing
```typescript
// src/app/app.routes.ts — application routes
import { Routes } from '@angular/router';
import { authGuard } from './auth/auth.guard';
export const routes: Routes = [
{ path: '', loadComponent: () => import('./home/home.component').then(m => m.HomeComponent) },
{ path: 'articles', loadComponent: () => import('./articles/article-list/article-list.component').then(m => m.ArticleListComponent) },
{ path: 'articles/:slug', loadComponent: () => import('./articles/article-detail/article-detail.component').then(m => m.ArticleDetailComponent) },
{ path: 'admin', loadComponent: () => import('./admin/admin.component').then(m => m.AdminComponent), canActivate: [authGuard] },
{ path: '**', redirectTo: '' },
];
```
## Guards and Interceptors
```typescript
// src/app/auth/auth.guard.ts — functional route guard
import { inject } from '@angular/core';
import { Router, CanActivateFn } from '@angular/router';
import { AuthService } from './auth.service';
export const authGuard: CanActivateFn = () => {
const auth = inject(AuthService);
const router = inject(Router);
return auth.isLoggedIn() ? true : router.createUrlTree(['/login']);
};
```
```typescript
// src/app/auth/auth.interceptor.ts — HTTP interceptor
import { HttpInterceptorFn } from '@angular/common/http';
import { inject } from '@angular/core';
import { AuthService } from './auth.service';
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const token = inject(AuthService).getToken();
if (token) {
req = req.clone({ setHeaders: { Authorization: `Bearer ${token}` } });
}
return next(req);
};
```
## Reactive Forms
```typescript
// src/app/articles/article-form/article-form.component.ts — reactive form
import { Component, inject } from '@angular/core';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { ArticleService } from '../article.service';
import { Router } from '@angular/router';
@Component({
selector: 'app-article-form',
standalone: true,
imports: [ReactiveFormsModule],
template: `
<form [formGroup]="form" (ngSubmit)="submit()">
<input formControlName="title" placeholder="Title" />
<textarea formControlName="body" placeholder="Body"></textarea>
<button type="submit" [disabled]="form.invalid">Create</button>
</form>
`,
})More from this repository
PULL_REQUEST_TEMPLATESkill
3dsmax-renderingSkill
>-
3dsmax-scriptingSkill
>-
3proxySkill
>-
a2a-protocolSkill
>-
ab-test-setupSkill
When the user wants to plan, design, or implement an A/B test or experiment. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," or "hypothesis." For tracking implementation, see analytics-tracking.
ablySkill
>-
accessibility-auditorSkill
>-