zustand-store-scaffold
Original:🇺🇸 English
Translated
1 scripts
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.
2installs
Sourceadonis0123/adonis-skills
Added on
NPX Install
npx skill4agent add adonis0123/adonis-skills zustand-store-scaffoldTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →Zustand Store Scaffold
Generate type-safe class-based Zustand stores with for prototype-safe slice composition.
flattenActionsQuick Start
Web Pattern (Component-level Store)
bash
python3 ~/.claude/skills/zustand-store-scaffold/scripts/scaffold_zustand_store.py \
--pattern web \
--name ToolList \
--path web/src/pages/_components/ToolList/storeGenerates:
- —
types.tstype definitionStoreSetter<T> - — Prototype-safe action flattener
utils/flattenActions.ts - — Class-based store with
index.ts+ActionImplflattenActions - — React Context and typed
context.tshookuseContext - — Memo-wrapped Provider component
provider.tsx
Core Pattern (Slice-based Store)
Single Slice:
bash
python3 ~/.claude/skills/zustand-store-scaffold/scripts/scaffold_zustand_store.py \
--pattern core \
--name CoreAgent \
--path packages/ag-ui-view/src/core/helpers/isomorphic/storeMultiple Slices (Interactive):
bash
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,uiMultiple Slices (Direct):
bash
python3 ~/.claude/skills/zustand-store-scaffold/scripts/scaffold_zustand_store.py \
--pattern core \
--name AppStore \
--path src/store \
--slices auth,user,uiGenerates:
- —
types.tstype definitionStoreSetter<T> - — Prototype-safe action flattener
utils/flattenActions.ts - — Store factory with
index.tsslice compositionflattenActions - — Class-based slice with
slices/[name].ts+ActionImplfields#private
Options
| Option | Required | Description | Example |
|---|---|---|---|
| Yes | Store pattern ( | |
| Yes | Store name in PascalCase | |
| Yes | Target directory path | |
| No | Comma-separated slice names (core only) | |
| No | Overwrite existing files | |
Note: For pattern without , the script interactively asks for slice names. Shared files (, ) are skipped if they already exist (unless ).
core--slicestypes.tsutils/flattenActions.ts--forceChoose 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 |
|---|---|
| |
| |
| Store factory combining initial state + |
| |
| React Context + typed selector hook |
| Memo-wrapped Provider with ref-stable store creation |
Post-Generation Steps
-
Define state ininterface (core) or
*SliceStateinterface (web):*StoreStatetsexport interface CoreSliceState { agents: Agent[] selectedId: string | null } -
Add action methods as arrow functions inclass:
*ActionImpltsexport 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:ts
const store = createCoreAgentStore({ initialState: { agents: [], selectedId: null } })
Usage Examples
Web Store Usage
tsx
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
ts
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 documentation
references/class-based-pattern.md - See for complete code examples
references/store-patterns.md - Reference PR: lobehub#12081