MANDATORY for creating Zustand stores. This skill is required when users request state management, creating stores, or mention Zustand. Do NOT create Zustand stores without this skill - all stores must use the required StoreBuilder pattern with immer middleware and factory pattern separation
Enforce a standardized, type-safe approach to creating Zustand stores that:
Use this skill when:
All Zustand stores MUST use the StoreBuilder utility located in assets/storebuilder.ts.
Copy the StoreBuilder utility (if not already in the project)
skills/superpower-zustand/assets/storebuilder.tssrc/lib/storebuilder.ts (or similar location in the project)Define state type separately from actions
Omit to exclude action methods when passing to StoreBuilderInitialize the store with StoreBuilder
Separate actions using createFactory
set from the StoreBuilder closureset callbacksExport the factory-created hook
import { StoreBuilder } from './storebuilder';
// 1. Define complete state type
type MyStoreState = {
// State fields
value: number;
items: string[];
// Action methods
setValue: (v: number) => void;
addItem: (item: string) => void;
};
// 2. Initialize StoreBuilder with state only (Omit actions)
const { set, createFactory } = StoreBuilder<Omit<MyStoreState, 'setValue' | 'addItem'>>(
{
value: 0,
items: [],
},
// Optional: persistence config
// {
// name: 'my-store',
// version: 1,
// }
);
// 3. Create factory with actions
const useMyStore = createFactory({
setValue: (v: number) => set((state) => { state.value = v; }),
addItem: (item: string) => set((state) => { state.items.push(item); }),
});
// 4. Export the hook
export { useMyStore };
When using set, write mutations directly on the draft state (immer middleware is included):
// ✅ Correct: Mutate draft
set((state) => {
state.count += 1;
state.items.push(newItem);
state.nested.property = 'value';
});
// ❌ Incorrect: Don't return new object
set((state) => ({ ...state, count: state.count + 1 }));
When state should persist across sessions:
const { createFactory } = StoreBuilder(
initialState,
{
name: 'storage-key', // Required: localStorage key
version: 1, // Optional: for migration handling
storage: sessionStorage, // Optional: defaults to localStorage
partialize: (state) => ({ // Optional: persist only specific fields
theme: state.theme,
preferences: state.preferences,
}),
}
);
For detailed examples and advanced patterns, read references/pattern-guide.md:
Load the reference documentation when:
After creating a store, verify:
Omit to exclude actionscreateFactory, not in initial stateuseMyStore)The pattern supports non-reactive access outside React components:
const { get, set, subscribe } = StoreBuilder(initialState);
// Get current state
const current = get();
// Update state
set((state) => { state.value = 10; });
// Subscribe to changes
const unsubscribe = subscribe((state) => console.log(state));
Use get and set when: