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

To reduce the complexity of the 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.

MethodParametersDescription
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.

EventParametersDescription
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

  1. Maintain immutability: Keep the Workspace instance immutable during runtime to prevent unexpected behavior
  2. Use unique IDs: Always provide a unique id for each workspace
  3. Handle errors: Subscribe to compileError events to handle compilation failures gracefully
  4. Cleanup subscriptions: Remember unsubscribe from events when components unmount to prevent memory leaks
  5. Normalize paths: Use relative paths starting with ./ for consistency across your workspace

Last updated on