ADR-002: Use Zustand for State Management
Date: 2025-10-06 Status: Accepted Deciders: Development Team Tags: state-management, architecture
Context​
The IDE requires complex state management across multiple features (editor, terminal, llm chat, file system). We need a solution that is simple, performant, and integrates well with React.
Decision​
We will use Zustand 4.4 as our primary state management library.
Rationale​
Why Zustand​
- Simplicity: Minimal boilerplate, easy to understand
- Performance: No provider needed, direct store access
- TypeScript: Excellent TypeScript support out of the box
- Bundle Size: ~1KB (vs Redux ~10KB)
- DevTools: Redux DevTools compatible
- Middleware: Persist, immer, devtools available
- Learning Curve: Minimal - just hooks
Key Features We Need​
- Multiple stores: Separate editor, llm, file, terminal stores
- Persistence: Session data survives refreshes
- Async actions: llm API calls, file operations
- No re-render overhead: Selector-based subscriptions
Alternatives Considered​
Redux Toolkit​
- Pros: Industry standard, extensive ecosystem, mature
- Cons: More boilerplate, provider wrapper needed, larger bundle
- Rejected: Overkill for our use case, unnecessary complexity
Recoil​
- Pros: Facebook-backed, atom-based, good for complex state
- Cons: Larger bundle, requires provider, experimental status
- Rejected: Less stable, more complex than needed
Jotai​
- Pros: Atomic state, minimal, TypeScript-first
- Cons: Different mental model, less documentation
- Rejected: Zustand more established, simpler API
Context API + useReducer​
- Pros: Built-in, no dependencies
- Cons: Performance issues, provider hell, no persistence
- Rejected: Not suitable for complex app-wide state
Consequences​
Positive​
- Fast development with minimal boilerplate
- Easy to test stores in isolation
- Good performance with selective re-renders
- Small bundle impact
- Easy migration path if needed (simple API)
Negative​
- Less "official" than Redux (community adoption)
- Fewer learning resources than Redux
- Middleware ecosystem smaller than Redux
Neutral​
- Need to establish store organization patterns
- Persistence middleware configuration required
Implementation​
Store Structure​
// editor-store.ts
interface editorStore {
tabs: editorTab[];
activeTabId: string | null;
addTab: (tab: editorTab) => void;
removeTab: (id: string) => void;
updateTab: (id: string, content: string) => void;
}
export const useeditorStore = create<editorStore>((set) => ({
tabs: [],
activeTabId: null,
addTab: (tab) => set((state) => ({
tabs: [...state.tabs, tab],
activeTabId: tab.id
})),
// ...
}));
With Persistence​
import { persist } from 'zustand/middleware';
export const usellmStore = create<llmStore>()(
persist(
(set) => ({
messages: [],
addMessage: (msg) => set((state) => ({
messages: [...state.messages, msg]
}))
}),
{ name: 'llm-storage' }
)
);
Store Organization​
src/store/
├── editor-store.ts # editor tabs, content
├── llm-store.ts # llm messages, config
├── fileStore.ts # File tree, OPFS
├── terminal-store.ts # terminal history, state
└── session-store.ts # Multi-session management *NEW*