Learn-skills.dev zustand-store-scaffold
Scaffold class-based Zustand stores with flattenActions: web (component-level store + Context + Provider) and core (slice-based store with immer). Class-based actions provide Go-to-Definition DX, #private field encapsulation, and prototype-safe slice composition.
install
source · Clone the upstream repo
git clone https://github.com/NeverSight/learn-skills.dev
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/NeverSight/learn-skills.dev "$T" && mkdir -p ~/.claude/skills && cp -r "$T/data/skills-md/adonis0123/adonis-skills/zustand-store-scaffold" ~/.claude/skills/neversight-learn-skills-dev-zustand-store-scaffold && rm -rf "$T"
manifest:
data/skills-md/adonis0123/adonis-skills/zustand-store-scaffold/SKILL.mdsource content
Zustand Store Scaffold
Generate type-safe class-based Zustand stores with
flattenActions for prototype-safe slice composition.
Quick Start
Web Pattern (Component-level Store)
python3 ~/.claude/skills/zustand-store-scaffold/scripts/scaffold_zustand_store.py \ --pattern web \ --name ToolList \ --path web/src/pages/_components/ToolList/store
Generates:
—types.ts
type definitionStoreSetter<T>
— Prototype-safe action flattenerutils/flattenActions.ts
— Class-based store withindex.ts
+ActionImplflattenActions
— React Context and typedcontext.ts
hookuseContext
— Memo-wrapped Provider componentprovider.tsx
Core Pattern (Slice-based Store)
Single Slice:
python3 ~/.claude/skills/zustand-store-scaffold/scripts/scaffold_zustand_store.py \ --pattern core \ --name CoreAgent \ --path packages/ag-ui-view/src/core/helpers/isomorphic/store
Multiple Slices (Interactive):
python3 ~/.claude/skills/zustand-store-scaffold/scripts/scaffold_zustand_store.py \ --pattern core \ --name AppStore \ --path src/store # Will prompt: Enter slice names (comma-separated, or press Enter for 'core'): # Example input: auth,user,ui
Multiple Slices (Direct):
python3 ~/.claude/skills/zustand-store-scaffold/scripts/scaffold_zustand_store.py \ --pattern core \ --name AppStore \ --path src/store \ --slices auth,user,ui
Generates:
—types.ts
type definitionStoreSetter<T>
— Prototype-safe action flattenerutils/flattenActions.ts
— Store factory withindex.ts
slice compositionflattenActions
— Class-based slice withslices/[name].ts
+ActionImpl
fields#private
Options
| Option | Required | Description | Example |
|---|---|---|---|
| Yes | Store pattern ( or ) | |
| Yes | Store name in PascalCase | |
| Yes | Target directory path | |
| No | Comma-separated slice names (core only) | |
| No | Overwrite existing files | |
Note: For
core pattern without --slices, the script interactively asks for slice names. Shared files (types.ts, utils/flattenActions.ts) are skipped if they already exist (unless --force).
Choose the Right Pattern
| Pattern | Use When | Location Pattern | Slices |
|---|---|---|---|
| web | Component-level state with Provider | | N/A |
| core | Isomorphic/shared state with slices | | Single or multiple |
When to Use Multiple Slices (Core Pattern)
Use multiple slices to organize complex state by feature domains:
| Scenario | Recommended Slices |
|---|---|
| Authentication app | |
| E-commerce store | |
| Dashboard | |
| Chat application | |
Generated Files
| File | Purpose |
|---|---|
| — type-safe overloaded setter matching Zustand internals |
| — walks prototype chain, binds methods, merges class instances |
| Store factory combining initial state + composition |
(core) | class with /, exported via |
(web) | React Context + typed selector hook |
(web) | Memo-wrapped Provider with ref-stable store creation |
Post-Generation Steps
-
Define state in
interface (core) or*SliceState
interface (web):*StoreStateexport interface CoreSliceState { agents: Agent[] selectedId: string | null } -
Add action methods as arrow functions in
class:*ActionImplexport class CoreActionImpl { readonly #set: StoreSetter<CoreSlice> readonly #get: () => CoreSlice // ...constructor selectAgent = (id: string): void => { this.#set({ selectedId: id }) } getSelectedAgent = (): Agent | undefined => { const { agents, selectedId } = this.#get() return agents.find((a) => a.id === selectedId) } } -
Set initial state in the store factory or config:
const store = createCoreAgentStore({ initialState: { agents: [], selectedId: null } })
Usage Examples
Web Store Usage
import Provider from './store/provider' import { useToolListContext } from './store/context' function ToolListPage() { return ( <Provider> <ToolListContent /> </Provider> ) } function ToolListContent() { const toolList = useToolListContext((s) => s.toolList) const setToolList = useToolListContext((s) => s.setToolList) // Go to Definition on setToolList → lands directly on ActionImpl method }
Core Store Usage
import { createCoreAgentStore } from './store' const store = createCoreAgentStore({ initialState: { agents: [], selectedId: null } }) // Vanilla JS const state = store.getState() state.selectAgent('agent-1') // React (with useStore) import { useStore } from 'zustand' function AgentList() { const agents = useStore(store, (s) => s.agents) const selectAgent = useStore(store, (s) => s.selectAgent) }
References
- See
for detailed pattern documentationreferences/class-based-pattern.md - See
for complete code examplesreferences/store-patterns.md - Reference PR: lobehub#12081