Loading...
Loading...
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.
npx skill4agent add adonis0123/adonis-skills zustand-store-scaffoldflattenActionspython3 ~/.claude/skills/zustand-store-scaffold/scripts/scaffold_zustand_store.py \
--pattern web \
--name ToolList \
--path web/src/pages/_components/ToolList/storetypes.tsStoreSetter<T>utils/flattenActions.tsindex.tsActionImplflattenActionscontext.tsuseContextprovider.tsxpython3 ~/.claude/skills/zustand-store-scaffold/scripts/scaffold_zustand_store.py \
--pattern core \
--name CoreAgent \
--path packages/ag-ui-view/src/core/helpers/isomorphic/storepython3 ~/.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,uipython3 ~/.claude/skills/zustand-store-scaffold/scripts/scaffold_zustand_store.py \
--pattern core \
--name AppStore \
--path src/store \
--slices auth,user,uitypes.tsStoreSetter<T>utils/flattenActions.tsindex.tsflattenActionsslices/[name].tsActionImpl#private| 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 | |
core--slicestypes.tsutils/flattenActions.ts--force| Pattern | Use When | Location Pattern | Slices |
|---|---|---|---|
| web | Component-level state with Provider | | N/A |
| core | Isomorphic/shared state with slices | | Single or multiple |
| Scenario | Recommended Slices |
|---|---|
| Authentication app | |
| E-commerce store | |
| Dashboard | |
| Chat application | |
| File | Purpose |
|---|---|
| |
| |
| Store factory combining initial state + |
| |
| React Context + typed selector hook |
| Memo-wrapped Provider with ref-stable store creation |
*SliceState*StoreStateexport interface CoreSliceState {
agents: Agent[]
selectedId: string | null
}*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)
}
}const store = createCoreAgentStore({
initialState: { agents: [], selectedId: null }
})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
}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/class-based-pattern.mdreferences/store-patterns.md