The component template gets one vm$ — an Observable that holds everything needed to render: user, route, permissions, loading. One vm$ | async in the template instead of four async pipes.
The problem it solves
Subscribe the template to 4 different Observables via async pipe and Angular subscribes 4 times to cold sources (4 HTTP requests!). Plus intermediate states — user arrived, permissions still null — the template renders a half-ready interface.
Operators and why they matter
combineLatest — gathers all sources into one stream. Any change to any one — a new VM.
map — computes derived state (canAdmin = permissions.includes('admin')) once, in one place.
shareReplay({ bufferSize: 1, refCount: true }) — several subscribers get the same VM. A late subscriber sees the last state immediately.
Gotchas
Without shareReplay, two vm$ | async in one template create two upstream subscriptions. Double HTTP requests.
Don't mix imperative fields with vm$. One source of truth — vm$.
If a source has no initial value, combineLatest stays silent until each has emitted once. Use startWith or a BehaviorSubject.
What you get
The template renders one consistent object. No intermediate "half-loaded" renders.