Documentation Index Fetch the complete documentation index at: https://docs.velt.dev/llms.txt
Use this file to discover all available pages before exploring further.
The @veltdev/codemirror-crdt-react library enables 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:
React / Next.js
Other Frameworks
npm install @veltdev/codemirror-crdt-react @veltdev/react
npm install @veltdev/codemirror-crdt @veltdev/client y-codemirror.next
Step 2: Setup Velt
Initialize the Velt client by following the Velt Setup Docs . This is required for the collaboration engine to work.
Step 3: Initialize Velt CRDT Extension
Initialize the Velt CRDT extension and use it to initialize 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.
React / Next.js
Other Frameworks
// Initialize the Velt CRDT extension
const { store , isLoading } = useVeltCodeMirrorCrdtExtension ({ editorId });
useEffect (() => {
if ( ! store || ! editorRef . current ) return ;
const startState = EditorState . create ({
doc: store . getYText ()?. toString () ?? '' ,
extensions: [
basicSetup ,
yCollab ( store . getYText () ! , store . getAwareness (), { undoManager: store . getUndoManager () }),
],
});
viewRef . current = new EditorView ({
state: startState ,
parent: editorRef . current ,
});
return () => viewRef . current ?. destroy ();
}, [ store ]);
// Create the CRDT store
const store = await createVeltCodeMirrorStore ({
editorId: editorId ,
veltClient: veltClient ,
});
// Create editor state with yCollab extension
const startState = EditorState . create ({
doc: store . getYText ()?. toString () ?? '' ,
extensions: [
basicSetup ,
yCollab ( store . getYText (), store . getAwareness (), {
undoManager: store . getUndoManager (),
}),
],
});
// Create editor view
const view = new EditorView ({
state: startState ,
parent: editorContainer ,
});
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 store’s Yjs text, awareness, and undo manager to yCollab.
Initialize and clean up : Destroy the EditorView and store on unmount to avoid leaks.
Testing and Debugging
To test collaboration:
Login two unique users on two browser profiles and open the same page in both.
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.
Complete Example
Open Live Demo In Larger Window | View Demo Repo // Import required modules
import { useVeltCodeMirrorCrdtExtension } from "@veltdev/codemirror-crdt-react" ;
import { yCollab } from "y-codemirror.next" ;
import { EditorState } from "@codemirror/state" ;
import { basicSetup , EditorView } from "codemirror" ;
// Add hook in your codemirror editor component
const { store , isLoading } = useVeltCodeMirrorCrdtExtension ({ editorId });
useEffect (() => {
if ( ! store || ! editorRef . current ) return ;
// Clean up existing view if any
viewRef . current ?. destroy ();
const startState = EditorState . create ({
doc: store . getYText ()?. toString () ?? '' ,
extensions: [
basicSetup ,
autocompletion (),
yCollab ( store . getYText () ! , store . getAwareness (), { undoManager: store . getUndoManager () }),
],
});
viewRef . current = new EditorView ({
state: startState ,
parent: editorRef . current ,
});
return () => {
viewRef . current ?. destroy ();
viewRef . current = null ;
};
}, [ store ]);
See all 34 lines
Open Live Demo In Larger Window | View Demo Repo // Import required modules
import { initVelt } from '@veltdev/client' ;
import { createVeltCodeMirrorStore } from '@veltdev/codemirror-crdt' ;
import { yCollab } from 'y-codemirror.next' ;
import { EditorState } from '@codemirror/state' ;
import { basicSetup , EditorView } from 'codemirror' ;
// Step 1: Initialize Velt client
const veltClient = await initVelt ( 'YOUR_API_KEY' );
// Step 2: Authenticate user
await veltClient . identify ({ userId: 'user-1' , name: 'John Doe' });
// Step 3: Set document
await veltClient . setDocument ( 'my-document-id' );
// Step 4: Create CRDT store
const store = await createVeltCodeMirrorStore ({
editorId: 'velt-codemirror-crdt-demo' ,
veltClient: veltClient ,
});
// Step 5: Create CodeMirror editor
const startState = EditorState . create ({
doc: store . getYText ()?. toString () ?? '' ,
extensions: [
basicSetup ,
yCollab ( store . getYText (), store . getAwareness (), {
undoManager: store . getUndoManager (),
}),
],
});
const view = new EditorView ({
state: startState ,
parent: document . getElementById ( 'editor' ),
});
// Cleanup on unmount
view . destroy ();
store . destroy ();
See all 41 lines
APIs
Custom Encryption
You can 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[].
React / Next.js
Other Frameworks
async function encryptData ( config : EncryptConfig < number []>) : Promise < string > {
const encryptedData = await yourEncryptDataMethod ( config . data );
return encryptedData ;
}
async function decryptData ( config : DecryptConfig < string >) : Promise < number []> {
const decryptedData = await yourDecryptDataMethod ( config . data );
return decryptedData ;
}
const encryptionProvider : VeltEncryptionProvider < number [], string > = {
encrypt: encryptData ,
decrypt: decryptData ,
};
< VeltProvider
apiKey = "YOUR_API_KEY"
encryptionProvider = { encryptionProvider }
/>
async function encryptData ( config : EncryptConfig < number []>) : Promise < string > {
const encryptedData = await yourEncryptDataMethod ( config . data );
return encryptedData ;
}
async function decryptData ( config : DecryptConfig < string >) : Promise < number []> {
const decryptedData = await yourDecryptDataMethod ( config . data );
return decryptedData ;
}
const encryptionProvider : VeltEncryptionProvider < number [], string > = {
encrypt: encryptData ,
decrypt: decryptData ,
};
client . setEncryptionProvider ( encryptionProvider );
See also: setEncryptionProvider()
· VeltEncryptionProvider
· EncryptConfig
· DecryptConfig
Initialization
React / Next.js
Other Frameworks
React hook that provides real-time collaborative editing on CodeMirror editor with Yjs and Velt SDK.
Signature: useVeltCodeMirrorCrdtExtension(config: VeltCodeMirrorCrdtExtensionConfig)
Params: VeltCodeMirrorCrdtExtensionConfig
editorId: Unique identifier for the editor instance.
initialContent: Initial content for the editor.
debounceMs: Debounce time for update propagation (ms).
Returns: VeltCodeMirrorCrdtExtensionResponse
store: CodeMirror CRDT store instance.
isLoading: Whether the store is initialized. false once store is initialized, true by default.
const { store , isLoading } = useVeltCodeMirrorCrdtExtension ({
editorId: 'velt-codemirror-crdt-demo'
});
Factory function that creates and initializes a VeltCodeMirrorStore instance for collaborative editing.
Signature: createVeltCodeMirrorStore(config: VeltCodeMirrorStoreConfig): Promise<VeltCodeMirrorStore | null>
Params: VeltCodeMirrorStoreConfig
editorId: Unique identifier for the editor instance.
veltClient: Velt client instance (from initVelt()).
initialContent: Optional initial content for the editor.
debounceMs: Optional debounce time for update propagation (ms).
Returns: Promise<VeltCodeMirrorStore | null> - The store instance or null if creation fails.
import { createVeltCodeMirrorStore } from '@veltdev/codemirror-crdt' ;
const store = await createVeltCodeMirrorStore ({
editorId: 'velt-codemirror-crdt-demo' ,
veltClient: client ,
initialContent: '// Start coding...' ,
});
Store Methods
Get the underlying Store<string> that manages document state and synchronization.
const underlying = store . getStore ();
Access the Yjs document used for collaborative editing.
const ydoc = store . getYDoc ();
Get the shared Y.Text bound to the current CodeMirror document.
const docText = store . getYText ()?. toString () ?? '' ;
Access the Yjs Awareness instance associated with the store.
yCollab ( store . getYText () ! , store . getAwareness (), { undoManager: store . getUndoManager () });
Access the Yjs UndoManager for collaborative undo/redo.
const extensions = [
basicSetup ,
yCollab ( store . getYText () ! , store . getAwareness (), { undoManager: store . getUndoManager () }),
];
Cleans up all resources, listeners, and destroys the store instance. Call this when unmounting the editor to prevent memory leaks.
// Cleanup when done
store . destroy ();