Loading...
Loading...
Angular 21 standalone frontend with Clean Architecture, vertical slice (pages by feature), signals, OnPush, and ng-zorro. Use when creating or refactoring Angular apps, adding pages, components, services, directives, pipes, or when the user mentions Angular frontend, standalone components, or signals.
npx skill4agent add luismpenholato/maurao-skills angular-frontend-clean-architecturepages/shared/components/shared/directives/shared/pipes/app.routes.tsfrontend/src/app/
├── app.ts # Bootstrap, providers (HTTP, interceptors)
├── app.config.ts # provideRouter, provideHttpClient, etc.
├── app.routes.ts # Rotas (guards quando necessário)
├── layout/ # Layout principal (header, drawer, outlet)
│ └── main-layout/
├── pages/ # Features por domínio (vertical slice)
│ └── products/
│ ├── product.model.ts
│ ├── product.service.ts
│ └── products-list/ # Uma tela = uma pasta com tudo junto
│ ├── products-list.component.ts
│ ├── products-list.component.html
│ ├── products-list.component.scss
│ └── products-list.component.spec.ts
├── shared/
│ ├── components/ # Componentes reutilizáveis (page-header, loading, etc.)
│ ├── directives/ # Diretivas (autofocus, currency-mask, etc.)
│ ├── pipes/
│ ├── services/ # Serviços globais (loading, layout)
│ ├── guards/
│ ├── interceptors/
│ └── utils/
└── environments/ # environment.apiBaseUrl, etc.pages/orders/order.model.tsOrderOrderCreateRequestpages/orders/order.service.ts@Injectable({ providedIn: 'root' })inject(HttpClient)Observable<T>environment.apiBaseUrlpages/orders/orders-list/*.component.ts*.component.html*.component.scss*.component.spec.tsChangeDetectionStrategy.OnPushhost: { class: 'app-orders-list' }inject(OrderService)@if@for[class.x][style.x]track item.id@forFormBuilderappCurrencyMaskapp.routes.tscanActivate: [authGuard]shared/standalone: trueimport { ChangeDetectionStrategy, Component, inject, input, signal } from '@angular/core';
@Component({
selector: 'app-page-header',
changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'app-page-header' },
imports: [RouterLink, NzBreadCrumbModule],
templateUrl: './page-header.component.html',
styleUrl: './page-header.component.scss'
})
export class PageHeaderComponent {
title = input.required<string>();
subtitle = input<string>();
breadcrumb = input<BreadcrumbItem[]>([]);
}@Injectable({ providedIn: 'root' })
export class ProductService {
private readonly http = inject(HttpClient);
private readonly baseUrl = `${environment.apiBaseUrl}/api/products`;
list(): Observable<Product[]> {
return this.http.get<Product[]>(this.baseUrl);
}
}@if (loading()) {
<nz-spin nzSimple></nz-spin>
} @else {
@for (item of items(); track item.id) {
<div [class.active]="item.isActive">{{ item.name }}</div>
}
}@Directive({
selector: '[appAutofocus]',
host: {
'(focus)': 'onFocus($event)'
}
})
export class AutofocusDirective {
readonly appAutofocus = input(true, { transform: booleanAttribute });
}host: { class: 'app-<nome>' }input()output()@Input()@Output()@if@for@switchtrack item.id@forngClassngStyleinject()providedIn: 'root'app.routes.tsshared/guards/appcatchErrorfinalizetimeoutNzMessageServiceloading[nzLoading]="loading()"LoadingService