| name | ngrx-feature-scaffold |
| description | Scaffolds a complete NgRx feature module (actions, reducer, effects, selectors, facade, models, tests) using modern Angular patterns. Use when adding a new feature slice to an Angular + NgRx app, standardizing existing ad-hoc state code, or bootstrapping state for a new library in an Nx monorepo. |
NgRx Feature Scaffold
Generate a coherent NgRx feature slice that follows current best practices:
createActionGroup with event-style action names
- Reducer + typed state interface + feature key constant
createFeatureSelector + composed selectors
- Effects using
exhaustMap / switchMap / concatMap appropriately
- Facade as the single component-facing API
- Colocated
.spec.ts tests for reducer, selectors, and facade
When to use
- Adding a new feature slice to an Angular + NgRx app.
- Bootstrapping state in a new Nx library.
- Replacing ad-hoc services-as-state with proper NgRx.
- Standardizing an existing feature that has drifted from the pattern.
Before you start
Ask (or derive from context) the following — defaults in square brackets:
- Feature name — kebab-case (e.g.
user-profile). Used for folder and action source.
- Feature key — usually the same word in camelCase (e.g.
userProfile). Used as the reducer key.
- State shape — what fields does this feature own? (entity? list? flags?)
- Data source — HTTP, WebSocket, both? Which service will effects call?
- Framework version — [
@ngrx/* 16+ for createActionGroup]. If older, fall back to createAction + union types.
Authoring workflow
- Create the
+state/ folder inside the feature's lib/app.
- Write files in this order — each one drives the next:
<feature>.models.ts — state interface + domain types
<feature>.actions.ts — createActionGroup with one event per use case
<feature>.reducer.ts — feature key, initial state, createReducer with on(...) handlers
<feature>.selectors.ts — feature selector + composed selectors
<feature>.effects.ts — one effect per async event, calls services via inject()
<feature>.facade.ts — exposes observables + dispatch methods
- Register the reducer and effects in the lib/app module.
- Write colocated
.spec.ts for reducer, selectors, and facade (see references).
- Verify: build passes, tests pass, DevTools shows dispatched actions.
Non-negotiable rules
- One facade is the only thing components inject. Components never import the store, actions, or selectors directly.
- Actions are events, not commands —
'Load User Success', not 'Set User'.
- Reducers are pure — no side effects, no service calls, no
Date.now() hidden inside.
- Effects use higher-order operators deliberately:
exhaustMap for idempotent one-shot loads (avoid duplicate in-flight).
switchMap for user-driven queries (cancel previous).
concatMap for writes that must preserve order.
- Never nested
subscribe().
- Selectors are composed, not recomputed in components.
- Every async op has loading + error flags in state (or a generic
RequestStatus discriminant).
providedIn: 'root' for the facade — singletons, no manual provider arrays.
References