How the SecureDesign VS Code Extension Persists and Restores State Across Restarts
The SecureDesign VS Code extension ensures state persistence across restarts by combining VS Code's Memento API for workspace data, a registered WebviewPanelSerializer for UI restoration, and the retainContextWhenHidden flag to preserve webview context.
The SecureDesign extension maintains chat history, selected design files, and canvas scroll positions even after VS Code shuts down or reloads. By implementing a layered persistence strategy across multiple VS Code APIs, the extension guarantees that users return to the exact UI state they left. This article examines the specific mechanisms found in the hbmartin/secure-design repository that make this seamless restoration possible.
Persisting Workspace Data with the Memento API
The extension persists small, serializable data pieces—such as chat history and selected workspace folders—using VS Code’s ExtensionContext.workspaceState. This Memento storage is wrapped by the WorkspaceStateService, a singleton initialized during extension activation that namespaces all keys to prevent collisions.
In src/services/workspaceStateService.ts, the service provides type-safe getter and setter methods that interact directly with the VS Code context:
public get<T>(key: string): T | undefined {
const context = this.ensureContext();
const workspaceKey = this.getNamespacedKey(key);
return context.workspaceState.get(workspaceKey);
}
public update<T>(key: string, value: T): Thenable<void> {
const context = this.ensureContext();
const workspaceKey = this.getNamespacedKey(key);
return context.workspaceState.update(workspaceKey, value);
}
The WorkspaceStateService is instantiated in the activate() function within src/extension.ts and shared across all services that require durable storage, ensuring that critical metadata survives full VS Code shutdowns.
Restoring Webview Panels After Reloads
To survive VS Code reloads, the extension registers a WebviewPanelSerializer for the SuperdesignCanvasPanel. This registration occurs in src/extension.ts and tells VS Code how to reconstruct the panel and restore its previous content when the editor restarts.
The serializer implementation receives the saved state object that the panel previously stored through VS Code’s internal persistence mechanism:
const canvasSerializer = vscode.window.registerWebviewPanelSerializer(
SuperdesignCanvasPanel.viewType,
{
deserializeWebviewPanel(webviewPanel, state) {
Logger.info('Restoring SuperdesignCanvasPanel from saved state');
SuperdesignCanvasPanel.deserialize(
webviewPanel,
state,
context.extensionUri,
sidebarProvider
);
return Promise.resolve();
},
}
);
When deserializeWebviewPanel is called, it invokes the static SuperdesignCanvasPanel.deserialize() method, which recreates the panel instance, re-adds it to the internal panels map, and prepares the webview to receive its restored UI state.
Managing Canvas UI State Serialization
The SuperdesignCanvasPanel class in src/SuperdesignCanvasPanel.ts defines a CanvasPanelState interface that tracks the workspace URI, currently selected design file, and scroll position. When users interact with the canvas—such as selecting a frame—the panel invokes _saveState() to post the current state to the webview:
private _saveState(): void {
const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
if (workspaceFolder && this._state) {
this._state.workspaceUri = workspaceFolder.uri.toString();
}
this._panel.webview.postMessage({ command: 'setState', state: this._state ?? {} });
}
VS Code automatically persists this state object between sessions. Upon deserialization, the panel calls _restoreState() to push the saved selection back to the webview’s frontend:
private _restoreState(): void {
if (this._state?.selectedFile) {
this._panel.webview.postMessage({
command: 'restoreSelection',
fileName: this._state.selectedFile,
});
}
}
This bidirectional message flow ensures that the UI appears exactly as the user left it, including precise scroll positions and file selections.
Preserving Context When Hidden
Both the sidebar webview and the canvas panel are created with retainContextWhenHidden: true set in their webview options. This setting prevents VS Code from destroying the webview’s DOM and internal JavaScript state when the user switches to another tab or panel.
Without this flag, the webview would lose its state before the extension could serialize it. By retaining the context, the extension maintains live UI state in memory and only relies on the Memento and serializer APIs for shutdown survival, not for tab switching.
Summary
- WorkspaceStateService wraps
ExtensionContext.workspaceStateto persist chat history and workspace selections across full VS Code shutdowns - The WebviewPanelSerializer registered in
activate()handles reconstruction ofSuperdesignCanvasPanelwhen VS Code reloads, receiving the previously saved state object automatically - Canvas panel state flows through
_saveState()and_restoreState()methods that communicate with the webview viapostMessageto restore exact UI selections and scroll positions retainContextWhenHidden: trueprevents state loss during tab switching by keeping the webview DOM alive while the panel is not visible
Frequently Asked Questions
How does SecureDesign store chat history between VS Code sessions?
Chat history and other workspace-specific metadata are stored via the WorkspaceStateService, which uses VS Code’s ExtensionContext.workspaceState Memento API. This service namespaces all keys and writes data to VS Code’s internal storage, which persists across restarts in workspace storage files.
What triggers the restoration of the design canvas after a reload?
When VS Code restarts, it automatically calls the registered WebviewPanelSerializer for SuperdesignCanvasPanel.viewType. The serializer’s deserializeWebviewPanel method receives the saved state object and invokes SuperdesignCanvasPanel.deserialize() to reconstruct the panel and its webview content.
Where is the persistent workspace state physically stored?
VS Code stores Memento data—accessed via workspaceState—in a SQLite database or JSON files within the workspace’s extension storage folder on disk. The exact location is managed by VS Code’s extension host, not by the SecureDesign extension directly.
Why doesn't the extension lose state when switching between editor tabs?
Both the sidebar provider and canvas panel webviews are created with the retainContextWhenHidden: true option. This prevents VS Code from discarding the webview’s DOM and JavaScript context when the user switches away, ensuring the UI remains live and ready without requiring deserialization.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →