redux-to-zustand-migrator
Installation
SKILL.md
Redux → Zustand/Context Migrator
Phase 1 — THINK
The trap in this migration is assuming Redux was "just boilerplate" — some of it was solving real problems (normalized state shape, memoized selectors, middleware-based side effects) that the new tool won't handle automatically.
- Inventory the store: which slices exist, and for each, whether it uses normalized data (entities keyed by ID) — this pattern needs to be deliberately preserved or consciously dropped, not lost by accident
- Identify any middleware in use (thunks, saga, custom logging/analytics middleware) — each needs an explicit new home (Zustand's setup functions, or component-level effects)
- Check for
reselect-style memoized selectors — Zustand/Context don't give you this for free, and losing memoization silently can cause real performance regressions in a frequently-updating app - Identify cross-slice logic (reducers/thunks that read from multiple slices) — this is the trickiest part to port since Zustand stores are more commonly siloed
Phase 2 — PLAN
- Store shape mapping: Redux slices → Zustand stores (one store or several, with reasoning)
- Explicit plan for normalized data: keep it normalized, or flatten it — state which and why
- Middleware → new-home mapping (thunk logic → async actions inside the Zustand store; saga-based side effects → explicit alternative, since sagas often encode non-trivial async coordination that needs real redesign, not a mechanical port)
- Memoized selector → replacement plan (Zustand selectors + shallow equality checks, or
useMemoat the call site)
Phase 3 — EXECUTE
- Migrate slice by slice, not all at once, so each can be verified independently
- Preserve normalized shape and memoization per the plan — don't let either quietly disappear
- Port middleware logic to its planned new home, preserving side-effect ordering/timing where it mattered (e.g., analytics events firing at the same point in the flow)