agentsclimarketplace

Angular frontend clean architecture

Skill luismpenholato/maurao-skills/skills/angular-frontend-clean-architecture

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.From its SKILL.md

Install
npx -y skills add luismpenholato/maurao-skills --skill angular-frontend-clean-architecture

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

6.3 KB, ~1.5k tokens by cl100k_base, as published. Nobody here has run it

Frontend Angular – Clean Architecture + Standalone

Guide for creating and maintaining Angular frontends with features structure (vertical slice), standalone components, signals, and ng-zorro-antd.

When to use

  • Add a new page/feature (new folder in pages/ with listing, form, service, models).
  • Create component in shared/components/, directive in shared/directives/, pipe in shared/pipes/.
  • Add service (HTTP, global state), guard, interceptor.
  • Define or change routes in app.routes.ts.
  • Review or refactor code to follow this skill's pattern.

When not to use

  • AngularJS or legacy non-Angular projects.
  • Codebases built on legacy NgModules without standalone components.
  • Applications that use another design system as the primary UI kit (e.g., Angular Material).
  • Library-only projects without routed pages or feature screens.

Target stack

TechnologyUsage
Angular 21Standalone, signals, @if / @for
ng-zorro-antd 21UI (tables, forms, layout)
RxJS 7HTTP and streams
TypeScript 5.9Typing
Vitest 4Tests via ng test

This skill uses ng-zorro-antd as the default design system, matching CleanStack. Do not force ng-zorro on projects that already use Angular Material or another UI kit — adapt the patterns while keeping the feature structure.

Project structure

src/
├── app/
│   ├── app.ts                    # Root (layout + overlays)
│   ├── app.config.ts             # provideRouter, provideHttpClient, …
│   ├── app.routes.ts             # Routes and guards
│   ├── layout/
│   │   └── main-layout/
│   ├── pages/                    # Features (vertical slice)
│   │   └── products/
│   │       ├── product.model.ts
│   │       ├── product.service.ts
│   │       ├── products-list/
│   │       └── product-form/
│   └── shared/
│       ├── components/           # page-header, loading, …
│       ├── directives/           # autofocus, currency-mask, …
│       ├── guards/               # authGuard (CanActivateFn)
│       ├── interceptors/
│       ├── pipes/
│       ├── services/             # loading, layout, confirmation
│       └── utils/
├── environments/                 # apiBaseUrl per environment
└── styles/                       # _tokens.scss, _ng-zorro-overrides.scss

Rule: pages/ = one folder per domain; inside it model, service, and one subfolder per screen. shared/ = only what is reusable across features.

Checklist – New feature (e.g., Orders)

Model and service

  • pages/orders/order.model.ts: interfaces (Order, OrderCreateRequest, …).
  • pages/orders/order.service.ts: @Injectable({ providedIn: 'root' }), inject(HttpClient), Observable methods. Base: `${environment.apiBaseUrl}/api/orders`.

Screens

  • One folder per screen (orders-list/, order-form/) with *.component.ts/html/scss/spec.
  • ChangeDetectionStrategy.OnPush, host: { class: 'app-orders-list' }, signals/computed.
  • Template: @if / @for with track; no ngClass/ngStyle.

Routes

  • app.routes.ts: feature routes; canActivate: [authGuard] when needed.

Shared (only if reusable)

  • Component/directive/pipe in shared/ only when used in more than one feature.

Code patterns

Standalone component (Angular 21 pattern — no standalone: true)

@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>();
}

Service with HttpClient

@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);
  }
}

Guard

export const authGuard: CanActivateFn = () => true; // replace with real auth

Conventions

  • Components: OnPush, host: { class: 'app-<name>' }, input()/output() with signals.
  • Templates: @if, @for, @switch; stable track in @for.
  • Services: inject(); providedIn: 'root' for globals.
  • Routes: app.routes.ts; guards in shared/guards/. UI path segments in English (products, new, edit); API at /api/products.
  • Environment: src/environments/ — never hardcode API URL in components.
  • Theme: src/styles/_tokens.scss + _ng-zorro-overrides.scss; toggle via LayoutService (body.theme-dark).
  • Drawer/menu: nzWrapClassName="app-drawer", *nzDrawerContent, CSS .app-drawer .drawer-menu (portaled to body).
  • SEO: title + data.description on routes; AppTitleStrategy; noindex in index.html (admin app).
  • Names: kebab-case in folders/files; app prefix on selectors.

Error handling and loading

  • HTTP: catchError, finalize, timeout; feedback via NzMessageService.
  • Loading: signal in component or LoadingService / global overlay in shared/services/.
  • Global errors: interceptor in shared/interceptors/.

Anti-patterns

  • Business logic in app.routes.ts instead of page components or services.
  • Hardcoded API URLs instead of environment.apiBaseUrl.
  • Using @Input() / @Output() in new standalone components instead of input() / output().
  • Placing entire features in shared/ instead of pages/.
  • Using ngClass / ngStyle when [class.x] / [style.x] suffices.

Additional resources

What ships with it: 1 file

3.6 KB alongside SKILL.md

Keep looking

Skills are one crate of 326,852. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.