State Management (Nano Stores)
Relevant source files
The following files were used as context for generating this wiki page:
State management in the Bolt.new-Builder project is primarily handled using Nano Stores, a tiny state manager for JS. It provides a reactive, modular, and framework-agnostic way to manage application state across different components such as the code editor, file system, and AI chat interface. By leveraging atoms and maps, the system ensures efficient updates and seamless synchronization between the browser-based WebContainer environment and the user interface.
Sources: app/lib/stores/workbench.ts:1, app/lib/stores/editor.ts:1
Core Architecture
The architecture relies on primitive store types from the nanostores library, including atom for single values and map for key-value objects. These stores are often wrapped in class-based "Store" objects that encapsulate logic for manipulating the underlying state.
Store Types and Usage
| Store Type | Description | Usage Example |
|---|---|---|
atom | Holds a single value of any type. | UI visibility toggles, selected file paths. |
map | Holds a collection of key-value pairs. | Managing multiple artifacts or editor documents. |
computed | Derived state that updates when dependencies change. | Determining the currentDocument based on selectedFile. |
WritableAtom | An atom that allows direct .set() operations. | Application-wide settings like showWorkbench. |
Sources: app/lib/stores/workbench.ts:1-20, app/lib/stores/editor.ts:5-15
Synchronization Flow
The following diagram illustrates how state flows from external file system changes through the stores to the UI components.
The system uses a 30-second interval to check for external file changes and synchronize the internal stores.
Sources: app/lib/stores/workbench.ts:108-115, app/lib/persistence/fileSystem.ts:153-170
Key Store Modules
Workbench Store
The WorkbenchStore acts as a central orchestrator. It manages the high-level UI state, including whether the workbench is visible and which view (code or preview) is currently active. It also handles the registration and execution of AI-generated artifacts and actions.
artifacts: AMapStorecontaining the state of all AI-generated tasks.unsavedFiles: ASetatom tracking files with pending changes.saveFile(filePath): Persists content to both the WebContainer and the local browser file system.
Sources: app/lib/stores/workbench.ts:31-60, app/lib/stores/workbench.ts:130-153
Editor Store
The EditorStore focuses on the state of the CodeMirror editor. It manages EditorDocuments, which include the file content and scroll positions.
// app/lib/stores/editor.ts:14-20
currentDocument = computed([this.documents, this.selectedFile], (documents, selectedFile) => {
if (!selectedFile) {
return undefined;
}
return documents[selectedFile];
});
This computed store ensures that whenever a user selects a different file in the sidebar, the editor automatically receives the correct document state.
Sources: app/lib/stores/editor.ts:7-25
FileSystem Persistence
While not a store itself, fileSystem.ts utilizes Nano Stores to bridge the Gap between the WebContainer and the user's local disk via the File System Access API.
selectedDirectoryHandle: An atom storing theFileSystemDirectoryHandle.fileChanges: An atom tracking differences between the in-memory state and the disk.
Sources: app/lib/persistence/fileSystem.ts:7-9, app/lib/persistence/fileSystem.ts:153-180
Artifact and Action Lifecycle
The project uses a structured flow to manage "Artifacts" (logical units of work provided by the AI) and "Actions" (specific steps like creating a file or running a shell command).
- Parsing: The
StreamingMessageParserdetects<boltArtifact>and<boltAction>tags in the AI stream. - Dispatching: It triggers callbacks that call
workbenchStore.addArtifactandworkbenchStore.addAction. - Execution: The
ActionRunner(instantiated within the artifact state) manages the lifecycle of the action, updating the status in the store.
Sources: app/lib/runtime/message-parser.ts:60-120, app/lib/stores/workbench.ts:192-230
Integration with React
React components consume these stores using the useStore hook from @nanostores/react. This ensures that components only re-render when the specific piece of state they are observing changes.
- Theme Management: The
Layoutcomponent inroot.tsxobserves thethemeStoreto update thedata-themeattribute on the HTML element. - Workbench UI:
Workbench.client.tsxobserves multiple stores (previews,showWorkbench,files) to toggle the visibility of panels and update the editor view.
Sources: app/root.tsx:63-70, app/components/workbench/Workbench.client.tsx:57-75
Summary
The Nano Stores implementation provides a robust and reactive backbone for the application. By separating the logic into specific stores (Workbench, Editor, Terminal, Files), the project achieves a high degree of modularity. This architecture supports complex features like real-time file synchronization, AI-driven code execution, and persistent local workspace management while maintaining high performance through granular state updates.