Angular Facade Pattern
Introduces or reviews Angular facades that provide a focused feature API over data access, state, permissions, navigation, and orchestration.
SKILL.mdskills/angular/architecture/facade-pattern/SKILL.md
GitHubAngular 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
- Identify coupling between components and low-level services.
- Decide whether a facade creates real value.
- Propose a bounded facade API.
- Move orchestration behind the facade incrementally.
- Provide testing guidance using facade mocks.