Angular Facade Pattern

Introduces or reviews Angular facades that provide a focused feature API over data access, state, permissions, navigation, and orchestration.

SKILL.md

GitHub

Angular Facade Pattern

Purpose

Use this skill to introduce a focused feature API between components and lower-level services. The goal is to reduce coupling, simplify tests, and keep orchestration out of UI components.

When to Use

Use this skill when:

  • A component injects many services from different concerns.
  • Components duplicate loading, error, permission, and mapping logic.
  • Tests require excessive mocks for one feature component.
  • Several components need the same feature-level operations.
  • Feature state and API calls need a stable public contract.
  • A module, route, or microfrontend boundary needs an explicit interface.

Do

Expose a narrow feature contract:

@Injectable()
export class UserFacade {
  readonly users$ = this.userState.users$;
  readonly loading$ = this.userState.loading$;
  readonly error$ = this.userState.error$;

  constructor(
    private readonly userApi: UserApiService,
    private readonly userState: UserStateService,
  ) {}

  loadUsers(): void {
    this.userState.setLoading(true);

    this.userApi
      .getUsers()
      .pipe(finalize(() => this.userState.setLoading(false)))
      .subscribe({
        next: (users) => this.userState.setUsers(users),
        error: (error) => this.userState.setError(error),
      });
  }
}

Keep the component simple:

readonly users$ = this.userFacade.users$;
readonly loading$ = this.userFacade.loading$;

ngOnInit(): void {
  this.userFacade.loadUsers();
}

Use a structure that reveals boundaries:

users/
  data-access/
    user-api.service.ts
    user-state.service.ts
  facade/
    user.facade.ts
  feature/
    users-page.component.ts
  ui/
    user-list.component.ts
  models/
    user.model.ts

Do Not

Avoid a facade that becomes a god service:

UserFacade
  - users
  - auth
  - payments
  - notifications
  - export
  - analytics

Avoid adding a facade for a trivial component if it only forwards one method and adds no stable boundary.

Avoid hiding bad domain boundaries behind a nicer class name.

Avoid mixing UI formatting, API calls, permissions, and unrelated business domains in the same facade.

Review Checklist

  • The facade owns one feature or bounded context.
  • Components depend on the facade instead of many low-level services.
  • Public facade properties are readonly.
  • Commands are named by user or feature intent.
  • Data access and state services remain separate when complexity justifies it.
  • The facade simplifies tests with fewer mocks.
  • The facade does not become a dumping ground.
  • Signals are only exposed when the Angular version and project style support them.

Expected Output

  1. Identify coupling between components and low-level services.
  2. Decide whether a facade creates real value.
  3. Propose a bounded facade API.
  4. Move orchestration behind the facade incrementally.
  5. Provide testing guidance using facade mocks.