Headless collaborative rich-text editor (Lexical + Yjs + Hocuspocus) shared across Omni products.
The package is product-agnostic: it ships the collaboration plumbing, a base
Lexical node set, and the core rich-text plugins, and exposes injection points
(nodes, plugins, AuthAdapter, AssetStorageAdapter) so each product wires
in its own auth, asset storage, and bespoke plugins (wikilinks, transclusions,
slash commands, etc.). Consumed by Trellis and Folio.
bun add @omnidotdev/editorLexical, Yjs, @hocuspocus/provider, and React are peer dependencies (install
them in the consuming app). y-indexeddb and lucide-react ship as
dependencies.
Collaboration:
useCollaboration(options)- React hook orchestrating the Y.Doc, IndexedDB persistence, and the Hocuspocus providercreateProvider(options)- build a Hocuspocus providercreatePersistence(documentId, ydoc, options)- build an IndexedDB persistence layergetOrCreateDoc,destroyDoc,hasDoc- Y.Doc lifecycle manager
Editor:
EditorCore- headless Lexical editor (collaborative or local-first)ImageNode,$createImageNode,$isImageNode- reusable image nodeTRANSFORMERS,IMAGE_TRANSFORMER- markdown transformersLocalContentPlugin- local-first markdown load/serialize pluginMobileToolbar- touch formatting toolbar
Adapters (types):
AuthAdapter-{ getToken: () => Promise<string> }AssetStorageAdapter-{ upload(file), resolve?(src) }
import { EditorCore, useCollaboration } from "@omnidotdev/editor";
const Editor = ({ documentId }: { documentId: string }) => {
const { ydoc, provider } = useCollaboration({
documentId,
url: import.meta.env.VITE_COLLABORATION_URL,
getToken: async () => myAuth.getToken(),
cloudEnabled: true,
persistence: { keyPrefix: "trellis-note-" },
onPeerCountChange: (n) => setPeerCount(n),
});
return (
<EditorCore
documentId={documentId}
ydoc={ydoc ?? undefined}
provider={provider}
username="Ada"
cursorColor="#DD6E33"
theme={myTheme}
nodes={[WikilinkNode]}
plugins={<WikilinkPlugin notes={notes} />}
/>
);
};<EditorCore
initialContent={markdown}
onContentChange={setMarkdown}
theme={myTheme}
/>bun install
bun run typecheck # tsc --noEmit
bun run build # bundle + emit declarations to build/
bun run check # biome
bun run knip # dead-code / unused-dependency check