Workspace
Learn how to use the Workspace API to manage files, editors, and compilation state in Codespark
The Workspace is the core state management system in Codespark. It manages files, tracks changes, handles compilation, and provides an event system for reacting to workspace updates.
Overview
A workspace represents a complete code environment with:
- File management: Create, read, update, delete, and rename files
- Editor integration: Track multiple editor instances
- Compilation state: Automatic dependency analysis and code compilation
- Event system: Subscribe to file changes, compilation events, and more
- OPFS support: Persist files using Origin Private File System
Get a Workspace
The Codespark component has an out-of-the-box internal workspace. You can use the getWorkspace prop to access it.
import { Codespark, type Workspace } from '@codespark/react';
import { useEffect, useRef } from 'react';
const code = `export default function App() {
return <div>Hello World</div>;
}`;
export default function App() {
const workspace = useRef<Workspace>(null);
useEffect(() => {
console.log(workspace.current?.files); // { './App.tsx': 'export default ...' }
}, []);
return <Codespark getWorkspace={workspace} code={code} />;
}Create a Workspace
Codespark component and maintain its out-of-the-box features, use composable components when you need to create a custom workspace.Using the Workspace Class
To keep the workspace immutable during runtime, create it outside the component or wrap it with useMemo.
import { CodesparkEditor, CodesparkPreview, CodesparkProvider, Workspace } from '@codespark/react';
const workspace = new Workspace({
entry: './App.tsx', // The entry file must be specified
files: { './App.tsx': '...' }
});
export default function App() {
// Or wrap with the useMemo hook
// const workspace = useMemo(() => new Workspace({ entry: './App.tsx', files: {...} }), [])
return (
<CodesparkProvider workspace={workspace}>
<div className="border-border relative w-full divide-y overflow-hidden rounded-lg border">
<CodesparkPreview className="border-border" />
<CodesparkEditor />
</div>
</CodesparkProvider>
);
}Using the useWorkspace Hook
Another way to create a workspace is to use the useWorkspace hook.
You can use this hook anywhere in your component tree. All properties returned from this hook are reactive and will trigger re-renders when updated.
import { CodesparkEditor, CodesparkPreview, CodesparkProvider, useWorkspace } from '@codespark/react';
import { useEffect } from 'react';
export default function App() {
const { workspace, files } = useWorkspace({ entry: './App.tsx', files: { './App.tsx': '' } });
useEffect(() => {
console.log('files:', files);
}, [files]);
return (
<CodesparkProvider workspace={workspace}>
<div className="border-border relative w-full divide-y overflow-hidden rounded-lg border">
<CodesparkPreview className="border-border" />
<CodesparkEditor />
</div>
</CodesparkProvider>
);
}Using the createWorkspace Function
The createWorkspace function provides a convenient way to create workspaces from React components.
It's useful when you want to make a component work directly instead of writing code as strings. It automatically collects all required dependencies and generates a workspace that may contain multiple files.
See this documentation to know more details.
import { createWorkspace } from '@codespark/react';
import { useState } from 'react';
// Use it as a normal Workspace
const workspace = createWorkspace(() => {
const [count, setCount] = useState(0);
return (
<div className="flex flex-col items-center gap-4 p-6">
<p className="text-2xl font-bold">{count}</p>
<button onClick={() => setCount(count + 1)} className="rounded-lg bg-black px-4 py-2 text-white">
Click me
</button>
</div>
);
});File Management Actions
The Workspace provides several APIs to help you manage files.
| Method | Parameters | Description |
|---|---|---|
setFile | (path: string, content: string) | Create or update a single file |
setFiles | (files: Record<string, string>) | Create or update multiple files simultaneously |
renameFile | (oldPath: string, newName: string) | Rename a file or folder (nested files are automatically renamed) |
deleteFile | (path: string) | Delete a file or folder (nested files are automatically deleted) |
setCurrentFile | (path: string) | Set the currently active file in the editor |
For more details, visit the File System and Workspace API reference documentation.
Event System
The Workspace emits events that you can subscribe to for reacting to changes in the workspace state.
| Event | Parameters | Description |
|---|---|---|
compiled | (code: string) | Emitted when code compiles successfully |
compileError | (error: Error) | Emitted when compilation fails |
fileChange | (path: string, content: string) | Emitted when a file is added or updated |
filesChange | (files: Record<string, string>) | Emitted when multiple files are updated |
fileRename | (oldPath: string, newPath: string) | Emitted when a file is renamed |
fileDelete | (path: string) | Emitted when a file is deleted |
currentFileChange | (file: FileNode) | Emitted when the current file changes |
import { Codespark, type Workspace } from '@codespark/react';
import { useEffect, useRef } from 'react';
export default function App() {
const workspace = useRef<Workspace>(null);
useEffect(() => {
if (!workspace.current) return;
return workspace.current.on('fileChange', (name, content) => {
console.log({ name, content });
});
}, []);
return <Codespark getWorkspace={workspace} />;
}Best Practices
- Maintain immutability: Keep the Workspace instance immutable during runtime to prevent unexpected behavior
- Use unique IDs: Always provide a unique
idfor each workspace - Handle errors: Subscribe to
compileErrorevents to handle compilation failures gracefully - Cleanup subscriptions: Remember unsubscribe from events when components unmount to prevent memory leaks
- Normalize paths: Use relative paths starting with
./for consistency across your workspace
Last updated on