React / Real-time / Collaboration

    CRDT i Collaborative Editing

    Y.js (CRDT Shared Types), Liveblocks (managed platform), PartyKit (serverless WebSockets), Hocuspocus i Tiptap — budowanie Notion-like collaborative editors.

    Y.js
    CRDT engine
    Liveblocks
    Managed
    PartyKit
    Serverless WS
    Tiptap
    Editor

    6 narzędzi collaborative editing — porównanie

    Y.js, Liveblocks, PartyKit, Hocuspocus, Automerge i ElectricSQL — typ, hosting i zastosowanie.

    Narzędzie Typ Hosting Kiedy
    Y.js CRDT Library Self-hosted Offline-first, własny backend, max kontrola
    Liveblocks Managed Platform SaaS (Cloudflare) Szybki start, gotowe UI, comments, notifications
    PartyKit Serverless WebSockets Cloudflare Workers Code-first, tanie skalowanie, Y.js backend
    Hocuspocus Y.js WebSocket Server Self-hosted Node.js Backend dla Y.js, auth, persistence
    Automerge CRDT Library (Rust) Self-hosted Automerge 2.0 (WASM), offline-first apps
    Electric SQL Local-first SQLite sync Self-hosted/Cloud SQL queries, offline, sync z Postgres

    Często zadawane pytania

    Co to są CRDTs i jak działają algorytmy collaborative editing?

    CRDT (Conflict-free Replicated Data Type): struktura danych dla distributed systems. Automatyczne merge bez konfliktów. Bez centralnego serwera. Eventual consistency. Jak działają: każda zmiana ma unikalny ID (UUID + timestamp). Operacje commutative — kolejność nie ma znaczenia. Merge zawsze daje ten sam wynik. Typy CRDT: G-Counter — tylko increment. PN-Counter — increment + decrement. G-Set — tylko dodawanie elementów. OR-Set — add i remove z unique tags. LWW-Register — Last Write Wins. MV-Register — Multi-Value. Sequence CRDT (dla tekstu): Logoot, LSEQ, RGA, Fugue. Ważne dla edytorów tekstu. Operational Transformation (OT): starsza alternatywa. Transformuje operacje przed zastosowaniem. Google Docs używa OT. Trudniejszy w implementacji. Więcej serwerów (transform server). CRDT vs OT: CRDT — P2P możliwe, prostszy server. OT — Google standard, sprawdzony. Lokalna-first architektura: edycja offline. Sync gdy połączenie wraca. Brak 'lost work'. Użytkownik zawsze może pracować. Y.js: najpopularniejsza CRDT implementacja. Shared Types: Y.Map, Y.Array, Y.Text. Providers: WebSocket, WebRTC, IndexedDB. Rich text z ProseMirror/Quill/Tiptap.

    Y.js — CRDT biblioteka dla collaborative editing?

    Y.js (Kevin Jahns): najpopularniejsza CRDT dla JavaScript. Instalacja: npm install yjs. Shared Types: Y.Doc — root dokument. Y.Map — jak JavaScript Map. Y.Array — jak JavaScript Array. Y.Text — rich text CRDT. Y.XmlFragment — XML/HTML CRDT. Podstawy: const ydoc = new Y.Doc(). const ymap = ydoc.getMap('config'). ymap.set('theme', 'dark'). ymap.observe(event => console.log(event.changes)). Y.Text z Tiptap: npm install @tiptap/extension-collaboration. TiptapExtension: Collaboration.configure({document: ydoc}). CollaborationCursor.configure({provider, user: {name, color}}). Providers: y-websocket: WebSocket sync. const provider = new WebsocketProvider('ws://localhost:1234', 'room', ydoc). y-webrtc: peer-to-peer sync. y-indexeddb: offline persistence. y-partykit: PartyKit integration. Awareness: kursory innych użytkowników. Presence informacje. provider.awareness.setLocalStateField('user', {name: 'Adam', color: '#ff0000'}). provider.awareness.on('change', changes => ...). Undo/Redo: Y.UndoManager([yText, yMap]). manager.undo(). manager.redo(). Wbudowane w Tiptap. Encoding: Y.encodeStateAsUpdate(ydoc). Y.applyUpdate(ydoc, update). Persist do DB — tylko delta. Garbage collection: ydoc.gc = false. Brak GC gdy offline. Uruchom po reconnect. Hocuspocus: backend Y.js server. WebSocket provider backend. Auth, persistence, extensions. Node.js lub Bun.

    Liveblocks — managed real-time collaboration platform?

    Liveblocks: managed real-time collaboration. Bez własnego serwera. Rooms, Presence, Storage, Comments, Notifications. Instalacja: npm install @liveblocks/client @liveblocks/react. Konfiguracja: createClient({publicApiKey: 'pk_...'}). createRoomContext (z typami). Presence: useMyPresence() — mój stan. useOthers() — inni użytkownicy. updateMyPresence({cursor: {x, y}}). Automatyczne broadcast do pokoju. Storage (CRDT-based): LiveObject, LiveList, LiveMap. useMutation hook: aktualizacja storage. useStorage hook: odczyt. Liveblocks Storage = Y.js pod spodem. Comments: useThreads() — wątki komentarzy. useCreateThread(), useCreateComment(). Notifications: useInboxNotifications(). useMarkInboxNotificationAsRead(). Ready-made UI: @liveblocks/react-ui. Thread, InboxNotification, FloatingComposer. Cursors: Cursor component. Pokazuje kursory innych użytkowników. Avatar i kolor per user. Auth: authEndpoint (server endpoint). Liveblocks weryfikuje token. Supabase/Clerk/NextAuth integration. Liveblocks vs Y.js: Liveblocks — managed, auth, UI components. Y.js — self-hosted, więcej kontroli. Liveblocks — szybszy start, płatny plan. Pricing: darmowy tier (starter). Płatny od enterprise. Liveblocks + Lexical: @liveblocks/react-lexical. Wbudowana collaborative editing. Cursors, presence, storage.

    PartyKit — serverless real-time collaboration?

    PartyKit (Sunil Pai, Cloudflare): serverless real-time platform. WebSockets na Cloudflare Workers. Durable Objects dla state. npm install partykit. Serwer PartyKit: src/server.ts. import {Party} from 'partykit/server'. export default class MyParty implements Party.Server { async onConnect(connection, room) { connection.send('hello') } async onMessage(message, sender, room) { room.broadcast(message) } }. Deploy: npx partykit deploy. Rooms: partysocket — klient WebSocket. import PartySocket from 'partysocket'. const socket = new PartySocket({host: 'myparty.youruser.partykit.dev', room: 'document-123'}). socket.addEventListener('message', handler). socket.send(JSON.stringify({type: 'update', data})). Persistence: Party.Storage — durable storage. await room.storage.put('state', data). await room.storage.get('state'). Durable Objects pod spodem. Y.js + PartyKit: y-partykit provider. npm install y-partykit. PartyKitServer (z y-partykit) jako serwer. new YPartyKitProvider('myhost.partykit.dev', 'room', ydoc). Presence w PartyKit: broadcast presence na każdy ruch. Filtruj własne connection. Skalowalność: Cloudflare global network. Niski latency. Autoscaling. Tańszy niż Liveblocks dla dużych użyć. PartyKit vs Liveblocks: PartyKit — code-first, Cloudflare. Liveblocks — managed, więcej features. PartyKit — tańszy przy scale. Liveblocks — gotowe UI components.

    Jak zbudować collaborative editor z React, Tiptap i Y.js?

    Stack: Tiptap (editor) + Y.js (CRDT) + Hocuspocus (backend) + React. Instalacja: npm install @tiptap/react @tiptap/starter-kit @tiptap/extension-collaboration @tiptap/extension-collaboration-cursor yjs @hocuspocus/provider. Konfiguracja: const ydoc = new Y.Doc(). const provider = new HocuspocusProvider({url: 'ws://localhost:1234', name: 'doc-1', document: ydoc}). Tiptap setup: useEditor({extensions: [StarterKit.configure({history: false}), Collaboration.configure({document: ydoc}), CollaborationCursor.configure({provider, user: {name: currentUser.name, color: randomColor()}})]}). Kursory innych: automatyczne z CollaborationCursor. CSS dla komentarzy. Hocuspocus server: npm install @hocuspocus/server. import {Server} from '@hocuspocus/server'. const server = Server.configure({port: 1234, extensions: [new Database({fetch: async({documentName}) => getFromDB(documentName), store: async({documentName, state}) => saveToDB(documentName, state)})]}). server.listen(). Offline support: y-indexeddb persist offline. const indexeddbProvider = new IndexeddbPersistence('doc-name', ydoc). indexeddbProvider.on('synced', () => console.log('loaded from db')). Gdy online: WebSocket sync z Hocuspocus. Merge automatyczny przez Y.js. Awareness kursory: type AwarenessState = {user: {name: string, color: string}, cursor: DecorationRange}. useEffect(() => { provider.setAwarenessField('user', currentUser) }). Undo/Redo: Tiptap History extension — wyłącz (conflict z Y.js). Y.UndoManager dla collaborative undo. Collaboration.configure — wbudowany undo. Persystencja: Hocuspocus Database extension. Postgres lub MongoDB. Binary Y.js state — małe delty. Snapshots: Y.encodeStateAsUpdate(ydoc). Wersjonowanie dokumentów.

    Czytaj dalej

    Powiązane artykuły

    Kontakt

    Skontaktuj się z nami

    Porozmawiajmy o Twoim projekcie. Bezpłatna wycena w ciągu 24 godzin.

    Wyślij zapytanie

    Bezpłatna wycena w 24h
    Bez zobowiązań
    Indywidualne podejście
    Ekspresowa realizacja

    Telefon

    +48 790 814 814

    Pon-Pt: 9:00 - 18:00

    Email

    adam@fotz.pl

    Odpowiadamy w ciągu 24h

    Adres

    Plac Wolności 16

    61-739 Poznań

    Godziny pracy

    Pon - Pt9:00 - 18:00
    Sob - NdzZamknięte

    Wolisz porozmawiać?

    Zadzwoń teraz i porozmawiaj z naszym specjalistą o Twoim projekcie.

    Zadzwoń teraz