Skip to main content

zustand-store-development

Guide for creating and modifying Zustand stores with IndexedDB persistence in the DEVS platform. Use this when asked to create a new store, modify store logic, or work with state management.

Source facts

Repository
codename-co/devs
Last source activity
January 16, 2026 at 23:22
Detected SKILL.md language
English
Stars
53
Forks
2

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
zustand-store-development
description
Guide for creating and modifying Zustand stores with IndexedDB persistence in the DEVS platform. Use this when asked to create a new store, modify store logic, or work with state management.
# Zustand Store Development for DEVS When creating or modifying Zustand stores in the DEVS platform, follow these patterns and best practices. ## Directory Structure Stores are located in `src/stores/`. Each store manages a specific domain entity. ## Store Pattern Template ```typescript import { create } from 'zustand' import { db } from '@/lib/db' import { toast } from '@/lib/toast' // 1. Define the store state interface interface EntityState { entities: Entity[] isLoading: boolean error: string | null } // 2. Define the store actions interface interface EntityActions { loadEntities: () => Promise<void> createEntity: (data: CreateEntityInput) => Promise<Entity> updateEntity: (id: string, updates: Partial<Entity>) => Promise<void> deleteEntity: (id: string) => Promise<void> getEntityById: (id: string) => Entity | undefined } // 3. Create the store with both state and actions export const useEntityStore = create<EntityState & EntityActions>( (set, get) => ({ // Initial state entities: [], isLoading: false, error: null, // Actions loadEntities: async () => { set({ isLoading: true, error: null }) try { const entities = await db.entities.toArray() set({ entities, isLoading: false }) } catch (error) { set({ error: (error as Error).message, isLoading: false }) toast.error('Failed to load entities') } }, createEntity: async (data) => { const entity: Entity = { id: crypto.randomUUID(), ...data, createdAt: new Date(), updatedAt: new Date(), } await db.entities.add(entity) set((state) => ({ entities: [...state.entities, entity] })) return entity }, updateEntity: async (id, updates) => { const updatedData = { ...updates, updatedAt: new Date() } await db.entities.update(id, updatedData) set((state) => ({ entities: state.entities.map((e) => e.id === id ? { ...e, ...updatedData } : e, ), })) }, deleteEntity: async (id) => { await db.entities.delete(id) set((state) => ({ entities: state.entities.filter((e) => e.id !== id), })) }, getEntityById: (id) => { return get().entities.find((e) => e.id === id) }, }), ) // 4. Export standalone functions for non-React contexts export const getEntityById = (id: string) => useEntityStore.getState().getEntityById(id) export const createEntity = (data: CreateEntityInput) => useEntityStore.getState().createEntity(data) export const updateEntity = (id: string, updates: Partial<Entity>) => useEntityStore.getState().updateEntity(id, updates) export const deleteEntity = (id: string) => useEntityStore.getState().deleteEntity(id) ``` ## Critical Rules 1. **Export standalone functions**: Always export functions directly for use in non-React contexts (lib/, orchestrator, etc.) ```typescript // ✅ Correct - use exported functions in lib code import { getAgentById, createAgent } from '@/stores/agentStore' // ❌ Wrong - don't use hooks in lib code const { getAgentById } = useAgentStore() ``` 2. **Database initialization**: Always check `db.isInitialized()` before operations if the store loads at app startup 3. **Optimistic updates**: Update local state immediately, then persist to IndexedDB 4. **Error handling**: Use try/catch with toast notifications for user feedback 5. **Timestamps**: Always update `updatedAt` when modifying entities ## Testing Requirements (TDD Mandatory) All store changes MUST follow TDD: 1. Create test file at `src/test/stores/{storeName}.test.ts` 2. Write failing tests first 3. Implement minimum code to pass 4. Run `npm run test:coverage` before committing Example test structure: ```typescript import { describe, it, expect, beforeEach, vi } from 'vitest' import { useEntityStore } from '@/stores/entityStore' describe('entityStore', () => { beforeEach(() => { useEntityStore.setState({ entities: [], isLoading: false, error: null }) }) describe('createEntity', () => { it('should create entity with correct structure', async () => { const result = await useEntityStore .getState() .createEntity({ name: 'Test' }) expect(result).toHaveProperty('id') expect(result.name).toBe('Test') }) }) }) ``` ## Existing Stores Reference - `agentStore` - AI agent management with slug generation - `taskStore` - Task lifecycle and requirement validation - `conversationStore` - Multi-agent chat history - `artifactStore` - Task deliverables - `contextStore` - Inter-agent context sharing - `userStore` - User preferences and settings - `agentMemoryStore` - Agent learning and memory
View on GitHub