Skip to main content
The @veltdev/codemirror-crdt-react and @veltdev/codemirror-crdt libraries enable real-time collaborative editing on CodeMirror Editors. The collaboration editing engine is built on top of Yjs and Velt SDK.

Prerequisites

  • Node.js (v14 or higher)
  • React (v16.8 or higher for hooks)
  • A Velt account with an API key (sign up)
  • Optional: TypeScript for type safety

Setup

Step 1: Install Dependencies

Install the required packages:
npm install @veltdev/codemirror-crdt-react @veltdev/codemirror-crdt @veltdev/react @veltdev/types codemirror @codemirror/state @codemirror/view y-codemirror.next yjs

Step 2: Setup Velt

Initialize the Velt client and set the document context. This is required for the collaboration engine to work.
Wrap your app with VeltProvider and use useSetDocument to scope the collaborative session.
import { VeltProvider, useSetDocument } from '@veltdev/react';

function App() {
  return (
    <VeltProvider apiKey="YOUR_API_KEY">
      <YourApp />
    </VeltProvider>
  );
}

function YourApp() {
  useSetDocument('my-codemirror-document', { documentName: 'My Document' });
  return <CodeMirrorEditor />;
}

Step 3: Initialize Collaborative Editor

  • Initialize the collaboration manager and use it to create the CodeMirror editor.
  • Pass an editorId to uniquely identify each editor instance you have in your app. This is especially important when you have multiple editors in your app.
Use the useCollaboration hook to manage the entire CRDT lifecycle. It creates a CollaborationManager, initializes the CRDT store, and returns collaboration primitives (ytext, awareness, undoManager, doc) that you pass to yCollab() from y-codemirror.next.
import { useCollaboration } from '@veltdev/codemirror-crdt-react';
import { EditorState } from '@codemirror/state';
import { EditorView, basicSetup } from 'codemirror';
import { yCollab } from 'y-codemirror.next';
import { useEffect, useRef } from 'react';

function CodeMirrorEditor() {
  const editorElRef = useRef<HTMLDivElement>(null);

  const { primitives, isLoading, isSynced, status, error, manager } = useCollaboration({
    editorId: 'my-codemirror-editor',
    initialContent: 'console.log("Hello!");',
    onError: (err) => console.error('Collaboration error:', err),
  });

  useEffect(() => {
    if (!primitives?.ytext || !editorElRef.current) return;

    const state = EditorState.create({
      doc: primitives.ytext.toString(),
      extensions: [
        basicSetup,
        yCollab(primitives.ytext, primitives.awareness, {
          undoManager: primitives.undoManager,
        }),
      ],
    });

    const view = new EditorView({ state, parent: editorElRef.current });
    return () => view.destroy();
  }, [primitives]);

  if (error) return <div>Error: {error.message}</div>;
  if (isLoading || !primitives) return <div>Connecting...</div>;

  return <div ref={editorElRef} />;
}

Step 4: Status Monitoring (Optional)

Monitor the connection status and sync state to display UI indicators.
The useCollaboration hook returns reactive status, isSynced, and error state:
const { primitives, isLoading, isSynced, status, error } = useCollaboration({
  editorId: 'my-codemirror-editor',
});

if (error) return <div>Error: {error.message}</div>;
if (isLoading) return <div>Connecting...</div>;

// In your JSX
<div>Status: {status} | Synced: {isSynced ? 'Yes' : 'No'}</div>

Step 5: Version Management (Optional)

Save and restore named snapshots of the document state.
The manager returned by useCollaboration provides version management methods:
// Save a version
const versionId = await manager.saveVersion('Before major edit');

// List all versions
const versions = await manager.getVersions();

// Restore a specific version
await manager.restoreVersion(versions[0].versionId);

Step 6: Force Reset Initial Content (Optional)

By default, initialContent is applied exactly once only when the document is brand new. Pass forceResetInitialContent: true to always overwrite remote data with initialContent on initialization.
const collab = useCollaboration({
  editorId: 'my-codemirror-editor',
  initialContent: '// Fresh start',
  forceResetInitialContent: true,
});

Step 7: CRDT Event Subscription (Optional)

Listen for real-time sync events using getCrdtElement().on() from the Velt client.
import { useVeltClient } from '@veltdev/react';

const { client } = useVeltClient();

useEffect(() => {
  if (!client) return;
  const crdtElement = client.getCrdtElement();
  const sub = crdtElement.on('updateData').subscribe((event) => {
    if (event) console.log('CRDT update:', event);
  });
  return () => sub?.unsubscribe?.();
}, [client]);

Step 8: Custom Encryption (Optional)

Encrypt CRDT data before it’s stored in Velt by registering a custom encryption provider. For CRDT methods, input data is of type Uint8Array | number[].
const encryptionProvider = {
  encrypt: async ({ data }) => data.map((n) => n.toString()).join('__'),
  decrypt: async ({ data }) => data.split('__').map((s) => parseInt(s, 10)),
};

<VeltProvider apiKey="YOUR_API_KEY" encryptionProvider={encryptionProvider}>
  ...
</VeltProvider>
See also: setEncryptionProvider() · VeltEncryptionProvider · EncryptConfig · DecryptConfig

Step 9: Error Handling (Optional)

Pass an onError callback to handle initialization or runtime errors. The error reactive state is also available for rendering.
const collab = useCollaboration({
  editorId: 'my-codemirror-editor',
  onError: (error) => console.error('Collaboration error:', error),
});

if (collab.error) {
  return <div>Error: {collab.error.message}</div>;
}

Step 10: Access Yjs Internals (Advanced)

The manager exposes escape hatches for direct Yjs manipulation when needed.
// From the manager returned by useCollaboration
const doc = manager.getDoc();
const text = manager.getText();
const awareness = manager.getAwareness();
const provider = manager.getProvider();
const store = manager.getStore();

Step 11: Cleanup

Cleanup is handled by calling manager.destroy(), which cascades to the store, provider, undo manager, and all listeners. Safe to call multiple times.
// Automatic on component unmount via useEffect cleanup
// Or manually:
manager.destroy();

Notes

  • Unique editorId: Use a unique editorId per editor instance.
  • Wait for auth: Initialize the store only after the Velt client is ready.
  • Use yCollab: Pass the Yjs text, awareness, and undo manager to yCollab.
  • Initialize and clean up: Destroy the EditorView and manager on unmount to avoid leaks.

Testing and Debugging

To test collaboration:
  1. Login two unique users on two browser profiles and open the same page in both.
  2. Edit in one window and verify changes and cursors appear in the other.
Common issues:
  • Cursors not appearing: Ensure each editor has a unique editorId and users are authenticated. Also ensure that you are logged in with two different users in two different browser profiles.
  • Editor not loading: Confirm the Velt client is initialized and the API key is valid.
  • Disconnected session: Check network.
Use the VeltCrdtStoreMap debugging interface to inspect and monitor your CRDT stores in real-time from the browser console.

Complete Example

A complete collaborative CodeMirror editor with user login, status display, and version management.App.tsx
Complete App.tsx
import { useMemo } from 'react';
import { VeltProvider, useSetDocument, useCurrentUser } from '@veltdev/react';
import { Header } from './Header';
import { EditorComponent } from './Editor';

const API_KEY = 'YOUR_API_KEY';

function getDocumentParams() {
  const params = new URLSearchParams(window.location.search);
  return {
    documentId: params.get('documentId') || 'codemirror-crdt-react-demo-doc-1',
    documentName: params.get('documentName') || 'CodeMirror CRDT React Demo',
  };
}

function AppContent() {
  const veltUser = useCurrentUser();
  const { documentId, documentName } = useMemo(() => getDocumentParams(), []);
  useSetDocument(documentId, { documentName });

  return (
    <div className="app-container">
      <Header />
      <main className="app-content">
        <EditorComponent key={veltUser?.userId || '__none__'} />
      </main>
    </div>
  );
}

export const App = () => (
  <VeltProvider apiKey={API_KEY}>
    <AppContent />
  </VeltProvider>
);
Editor.tsx
Complete Editor.tsx
import { useEffect, useRef, useState, useCallback } from 'react';
import { useCurrentUser } from '@veltdev/react';
import { useCollaboration } from '@veltdev/codemirror-crdt-react';
import { EditorState } from '@codemirror/state';
import { EditorView, basicSetup } from 'codemirror';
import { javascript } from '@codemirror/lang-javascript';
import { yCollab } from 'y-codemirror.next';
import type { Version } from '@veltdev/crdt';

const DEFAULT_INITIAL_CONTENT = 'console.log("Hello CodeMirror CRDT!");';

export const EditorComponent = () => {
  const editorElRef = useRef<HTMLDivElement>(null);
  const viewRef = useRef<EditorView | null>(null);
  const [versions, setVersions] = useState<Version[]>([]);
  const [versionInput, setVersionInput] = useState('');
  const veltUser = useCurrentUser();

  const { primitives, isLoading, isSynced, status, error, manager } = useCollaboration({
    editorId: 'my-document-id',
    initialContent: DEFAULT_INITIAL_CONTENT,
    onError: (err) => console.error('Collaboration error:', err),
  });

  // Create CodeMirror editor when primitives are ready
  useEffect(() => {
    if (!primitives?.ytext || !editorElRef.current || viewRef.current) return;

    const state = EditorState.create({
      doc: primitives.ytext.toString(),
      extensions: [
        basicSetup,
        javascript(),
        EditorView.lineWrapping,
        yCollab(primitives.ytext, primitives.awareness, {
          undoManager: primitives.undoManager,
        }),
      ],
    });

    viewRef.current = new EditorView({ state, parent: editorElRef.current });

    return () => {
      viewRef.current?.destroy();
      viewRef.current = null;
    };
  }, [primitives]);

  // Version management
  const refreshVersions = useCallback(async () => {
    if (!manager) return;
    setVersions(await manager.getVersions());
  }, [manager]);

  useEffect(() => { refreshVersions(); }, [manager, refreshVersions]);

  const handleSaveVersion = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!manager || !versionInput.trim()) return;
    await manager.saveVersion(versionInput.trim());
    setVersionInput('');
    await refreshVersions();
  };

  const handleRestoreVersion = async (versionId: string) => {
    if (!manager) return;
    await manager.restoreVersion(versionId);
    await refreshVersions();
  };

  if (error) return <div>Error: {error.message}</div>;
  if (isLoading || !primitives) return <div>Connecting...</div>;

  return (
    <div className="editor-container">
      <div id="editor-header">
        {veltUser ? `Editing as ${veltUser.name}` : 'Please login'}
      </div>
      <div id="status">
        Status: {status} | Synced: {isSynced ? 'Yes' : 'No'}
      </div>
      <div id="editor" ref={editorElRef} />
      <div className="versions-section">
        <form onSubmit={handleSaveVersion}>
          <input
            className="version-input"
            value={versionInput}
            onChange={(e) => setVersionInput(e.target.value)}
            placeholder="Version name..."
          />
          <button className="save-version-btn" type="submit">Save Version</button>
        </form>
        <ul className="version-list">
          {versions.map((v) => (
            <li key={v.versionId} className="version-item">
              <span className="version-name">{v.versionName}</span>
              <button className="restore-btn" onClick={() => handleRestoreVersion(v.versionId)}>
                Restore
              </button>
            </li>
          ))}
        </ul>
      </div>
    </div>
  );
};

How It Works

  1. useCollaboration (React) / createCollaboration (non-React) creates a CollaborationManager. This initializes a CRDT Store (type: 'text'), a Yjs Y.Text, and a SyncProvider.
  2. The primitives (ytext, awareness, undoManager, doc) are returned by the hook or via manager.getCollaborationPrimitives(). You pass these to yCollab() from y-codemirror.next as a CodeMirror extension.
  3. User types -> CodeMirror transaction -> Y.Text mutation -> Yjs CRDT broadcasts via Velt backend -> all connected clients see the change.
  4. Remote cursors are tracked via Yjs Awareness. The yCollab extension renders colored cursor indicators at each remote user’s selection position.
  5. Initial content is applied only once for brand-new documents. The manager waits for remote content before deciding the document is new.
  6. Conflict resolution is handled by Yjs CRDTs, concurrent typing at different positions merges correctly.
  7. Version management saves the full Yjs state as a named snapshot. Restoring a version replaces the current state and broadcasts to all clients.
  8. Cleanup is automatic, the manager destroys the editor bindings, store, and all listeners when destroyed or the component unmounts.

APIs

React: useCollaboration()

The primary React hook for collaborative CodeMirror editing. Creates a CollaborationManager, initializes the CRDT store, and returns collaboration primitives for CodeMirror integration.
  • Signature: useCollaboration(config: UseCollaborationConfig)
  • Params: UseCollaborationConfig
    • editorId: Unique identifier for this collaborative session.
    • initialContent: Text content applied once for brand-new documents.
    • debounceMs: Throttle interval (ms) for backend writes. Default: 0.
    • forceResetInitialContent: If true, always clear and re-apply initialContent. Default: false.
    • veltClient: Explicit Velt client. Falls back to VeltProvider context.
    • onError: Error callback.
  • Returns: UseCollaborationReturn
    • primitives: Yjs primitives for CodeMirror. null while loading.
    • isLoading: true until CollaborationManager is initialized.
    • isSynced: true after the initial sync with the backend completes.
    • status: Connection status: 'connecting', 'connected', or 'disconnected'.
    • error: Most recent error, or null.
    • manager: The underlying CollaborationManager. null before initialization.
const { primitives, isLoading, isSynced, status, error, manager } = useCollaboration({
  editorId: 'my-codemirror-editor',
  initialContent: 'console.log("Hello!");',
  onError: (err) => console.error('Collaboration error:', err),
});

Non-React: createCollaboration()

Factory function that creates a CollaborationManager, calls initialize(), and returns a ready-to-use instance.
  • Signature: createCollaboration(config: CollaborationConfig): Promise<CollaborationManager>
  • Params: CollaborationConfig
    • editorId: Unique editor/document identifier for syncing.
    • veltClient: Velt client instance must have an authenticated user.
    • initialContent: Plain text content applied once for brand-new documents.
    • debounceMs: Throttle interval (ms) for backend writes. Default: 0.
    • onError: Callback for non-fatal errors.
    • forceResetInitialContent: If true, always reset to initialContent. Default: false.
  • Returns: Promise<CollaborationManager>
import { createCollaboration } from '@veltdev/codemirror-crdt';

const manager = await createCollaboration({
  editorId: 'my-document-id',
  veltClient: client,
  initialContent: 'Hello world',
  onError: (error) => console.error(error),
});

CollaborationPrimitives

The primitives object (from the React hook) or manager.getCollaborationPrimitives() (non-React) contains everything you need to set up yCollab():
PropertyTypeDescription
ytextY.Text | nullY.Text bound to the document. Pass to yCollab().
awarenessAwarenessAwareness instance for cursor/presence tracking.
undoManagerY.UndoManager | nullCollaborative undo manager (tracks local changes only).
docY.DocUnderlying Yjs document.

CollaborationManager Methods

Once the manager is available (non-null from the hook, or returned from createCollaboration), you can use its full API:

manager.getCollaborationPrimitives()

Returns the Yjs primitives needed to call yCollab(). Non-React only, the React hook returns primitives directly.
  • Returns: { ytext: Y.Text | null, awareness: Awareness, undoManager: Y.UndoManager | null, doc: Y.Doc }
const { ytext, awareness, undoManager } = manager.getCollaborationPrimitives();

manager.onStatusChange()

Subscribe to connection status changes.
  • Signature: manager.onStatusChange(callback: (status: SyncStatus) => void): Unsubscribe
  • Returns: Unsubscribe (call to stop listening)
const unsubscribe = manager.onStatusChange((status) => {
  console.log('Connection:', status);
});

unsubscribe(); // Stop listening

manager.onSynced()

Subscribe to sync state changes.
  • Signature: manager.onSynced(callback: (synced: boolean) => void): Unsubscribe
  • Returns: Unsubscribe
const unsubscribe = manager.onSynced((synced) => {
  if (synced) console.log('Initial sync complete');
});

manager.initialized

Whether initialize() has completed.
  • Returns: boolean

manager.synced

Whether initial sync with the backend has completed.
  • Returns: boolean

manager.status

Current connection status.
  • Returns: SyncStatus ('connecting' | 'connected' | 'disconnected')

manager.saveVersion()

Save a named snapshot. Returns the version ID.
  • Signature: manager.saveVersion(name: string): Promise<string>
  • Returns: Promise<string>
const versionId = await manager.saveVersion('Before major edit');

manager.getVersions()

List all saved versions.
  • Returns: Promise<Version[]>
const versions = await manager.getVersions();

manager.restoreVersion()

Restore to a saved version. Returns true on success. The restored state is pushed to all connected clients.
  • Signature: manager.restoreVersion(versionId: string): Promise<boolean>
  • Returns: Promise<boolean>
await manager.restoreVersion(versions[0].versionId);

manager.setStateFromVersion()

Apply a Version object’s state locally to the current document.
  • Signature: manager.setStateFromVersion(version: Version): Promise<void>
  • Returns: Promise<void>
const versions = await manager.getVersions();
const version = versions.find((v) => v.versionId === targetVersionId);
if (version) {
  await manager.setStateFromVersion(version);
}

manager.getDoc()

Get the underlying Yjs document.
  • Returns: Y.Doc
const doc = manager.getDoc();

manager.getText() / manager.getYText()

Get the Y.Text bound to the document content. In React, this method is called getText(); in non-React, it is called getYText().
  • Returns: Y.Text | null
const text = manager.getText();   // React
const ytext = manager.getYText(); // Non-React

manager.getProvider()

Get the sync provider.
  • Returns: SyncProvider
const provider = manager.getProvider();

manager.getAwareness()

Get the Yjs Awareness instance.
  • Returns: Awareness
const awareness = manager.getAwareness();

manager.getStore()

Get the core CRDT Store.
  • Returns: Store<string>
const crdtStore = manager.getStore();

manager.getUndoManager()

Get the Y.UndoManager for undo/redo operations.
  • Returns: Y.UndoManager | null
const undoManager = manager.getUndoManager();

manager.destroy()

Full cleanup (automatic on editor destroy or component unmount). Safe to call multiple times.
  • Returns: void
manager.destroy();

Migration Guide: v1 to v2

React

Overview

The v2 API replaces useVeltCodeMirrorCrdtExtension() with useCollaboration(). The new hook provides richer reactive state (status, sync, error), returns Yjs primitives directly, and exposes the CollaborationManager for advanced use.

Key Changes

Aspectv1 (deprecated)v2 (current)
Entry pointuseVeltCodeMirrorCrdtExtension(config)useCollaboration(config)
Yjs accessstore.getYText(), store.getAwareness()primitives.ytext, primitives.awareness
Undo managerstore.getUndoManager()primitives.undoManager
Manager accessstore (VeltCodeMirrorStore)manager (CollaborationManager)
Version managementstore.saveVersion(), store.getVersions()manager.saveVersion(), manager.getVersions()
Status trackingNot availablestatus, isSynced (reactive state)
Error handlingNot availableonError callback + error state
CleanupAutomatic on unmountAutomatic on unmount

Step-by-Step

1. Replace the hook:
// Before (v1)
import { useVeltCodeMirrorCrdtExtension } from '@veltdev/codemirror-crdt-react';
const { store, isLoading } = useVeltCodeMirrorCrdtExtension({ editorId: 'my-doc' });

// After (v2)
import { useCollaboration } from '@veltdev/codemirror-crdt-react';
const { primitives, isLoading, isSynced, status, error, manager } = useCollaboration({
  editorId: 'my-doc',
  onError: (err) => console.error(err),
});
2. Replace editor creation:
// Before (v1): store.getYText(), store.getAwareness(), store.getUndoManager()
// After (v2): primitives.ytext, primitives.awareness, primitives.undoManager
3. Replace version management:
// Before (v1): store.getVersions(), store.setStateFromVersion(version)
// After (v2): manager.getVersions(), manager.restoreVersion(versionId)
4. Add status monitoring (new in v2):
if (error) return <div>Error: {error.message}</div>;
if (isLoading) return <div>Connecting...</div>;
<div>Status: {status} | Synced: {isSynced ? 'Yes' : 'No'}</div>

Non-React

Overview

The v2 API replaces the callback-based createVeltCodeMirrorCrdtExtension() with an async createCollaboration() factory that returns a CollaborationManager.

Key Changes

Aspectv1 (deprecated)v2 (current)
Entry pointcreateVeltCodeMirrorCrdtExtension(config, callback)await createCollaboration(config)
Return valueCleanup functionCollaborationManager instance
Yjs primitivesVia callback: store.getYText(), store.getAwareness()Via method: manager.getCollaborationPrimitives()
Store accessVia callback: response.storeVia method: manager.getStore()
Version managementstore.getEncodedState(), store.setStateFromVersion()manager.saveVersion(), manager.getVersions()
Status trackingNot availablemanager.onStatusChange(), manager.onSynced()
CleanupCall returned cleanup functionmanager.destroy()
Error handlingonConnectionError callbackonError callback
Sync notificationonSynced callback (fires once)manager.onSynced() (subscribable)

Step-by-Step

1. Replace the store creation:
// Before (v1)
import { createVeltCodeMirrorCrdtExtension } from '@veltdev/codemirror-crdt';
const cleanup = createVeltCodeMirrorCrdtExtension(
  { editorId: 'my-doc', veltClient: client },
  ({ store }) => {
    const state = EditorState.create({
      doc: store.getYText()?.toString() ?? '',
      extensions: [basicSetup, yCollab(store.getYText()!, store.getAwareness(), { undoManager: store.getUndoManager() })],
    });
    new EditorView({ state, parent: document.querySelector('#editor') });
  }
);

// After (v2)
import { createCollaboration } from '@veltdev/codemirror-crdt';
const manager = await createCollaboration({ editorId: 'my-doc', veltClient: client });
const { ytext, awareness, undoManager } = manager.getCollaborationPrimitives();
const state = EditorState.create({
  doc: ytext.toString(),
  extensions: [basicSetup, yCollab(ytext, awareness, { undoManager })],
});
new EditorView({ state, parent: document.querySelector('#editor') });
2. Replace version management:
// Before (v1): store.getEncodedState(), store.setStateFromVersion(version)
// After (v2): manager.saveVersion('v1'), manager.restoreVersion(versionId)
3. Replace cleanup:
// Before (v1): cleanup()
// After (v2): manager.destroy()
4. Add status monitoring (new in v2):
manager.onStatusChange((status) => console.log('Status:', status));
manager.onSynced((synced) => console.log('Synced:', synced));
5. Access Yjs internals:
// Before (v1): store.getYDoc(), store.getYText(), store.getAwareness(), store.getUndoManager()
// After (v2): manager.getDoc(), manager.getYText(), manager.getAwareness(), manager.getUndoManager(), manager.getProvider()

Legacy API (v1)

The v1 API is deprecated. Use the v2 useCollaboration hook (React) or createCollaboration (non-React) for all new integrations. The v1 API is still exported for backward compatibility.

React: useVeltCodeMirrorCrdtExtension() (deprecated)

A React hook that returns a store for CodeMirror integration. Internally delegates to useCollaboration (v2) via a compatibility wrapper.
import { useVeltCodeMirrorCrdtExtension } from '@veltdev/codemirror-crdt-react';

const { store, isLoading } = useVeltCodeMirrorCrdtExtension({
  editorId: 'my-document-id',
  initialContent: 'console.log("Hello!");',
});

// Use store to create CodeMirror extensions
if (store) {
  const state = EditorState.create({
    doc: store.getYText()?.toString() ?? '',
    extensions: [
      basicSetup,
      yCollab(store.getYText()!, store.getAwareness(), {
        undoManager: store.getUndoManager(),
      }),
    ],
  });
}

React: VeltCodeMirrorCrdtExtensionConfig (deprecated)

PropertyTypeRequiredDescription
editorIdstringYesUnique editor identifier.
initialContentstringNoText content for new documents.
debounceMsnumberNoThrottle interval (ms).
veltClientVeltNoVelt client instance.

React: VeltCodeMirrorCrdtExtensionResponse (deprecated)

PropertyTypeDescription
storeVeltCodeMirrorStore | nullStore instance for editor and version management.
isLoadingbooleantrue until the store is ready.

Non-React: createVeltCodeMirrorCrdtExtension() (deprecated)

Creates a collaboration store using a callback-based pattern. The function subscribes to the Velt SDK lifecycle and invokes the onReady callback when the store is ready.
  • Signature: createVeltCodeMirrorCrdtExtension(config: VeltCodeMirrorStoreConfig, onReady: (response) => void): () => void
  • Returns: () => void (cleanup function)
import { createVeltCodeMirrorCrdtExtension } from '@veltdev/codemirror-crdt';

const cleanup = createVeltCodeMirrorCrdtExtension(
  {
    editorId: 'my-document-id',
    veltClient: client,
    initialContent: 'Hello world',
  },
  ({ store }) => {
    if (store) {
      const state = EditorState.create({
        doc: store.getYText()?.toString() ?? '',
        extensions: [
          basicSetup,
          yCollab(store.getYText()!, store.getAwareness(), { undoManager: store.getUndoManager() }),
        ],
      });
      new EditorView({ state, parent: document.querySelector('#editor') });
    }
  }
);

// Call cleanup() to tear down
cleanup();

Non-React: VeltCodeMirrorStoreConfig (deprecated)

PropertyTypeRequiredDescription
editorIdstringYesUnique editor identifier.
initialContentstringNoText content for new documents.
debounceMsnumberNoThrottle interval (ms).
onSynced(doc?: Y.Doc) => voidNoCalled once when initial sync completes.
onConnectionError(error: Error) => voidNoCalled on connection errors.
veltClientVeltNoVelt client instance.

Non-React: VeltCodeMirrorCrdtExtensionResponse (deprecated)

PropertyTypeDescription
storeVeltCodeMirrorStore | nullStore instance for Yjs access and versions.
errorstring | nullError message if initialization failed.

VeltCodeMirrorStore Methods (deprecated)

MethodReturnsDescription
getStore()Store<string>Get the core CRDT Store.
getYText()Y.Text | nullGet the Yjs Text instance.
getYDoc()Y.DocGet the Yjs Doc.
getUndoManager()Y.UndoManager | nullGet the Yjs UndoManager.
getAwareness()AwarenessGet the Awareness instance.
getEncodedState()number[]Get encoded Y.Doc state for versioning.
isConnected()booleanCheck if connected to backend.
setStateFromVersion(v)Promise<void>Apply a version’s state.
destroy()voidClean up all resources.