Hocuspocus

repository·main·Indexed 11 days ago

https://github.com/ueberdosis/hocuspocus

A plug-and-play collaboration backend based on Y.js that provides a WebSocket server for real-time collaborative applications. It includes a CLI for quick deployment and a variety of extensions for persistence (SQLite, S3, and a generic Database extension), horizontal scaling via Redis, logging, and IP-based rate-limiting via a throttle extension.

Tokens
33.3K
Snippets
122
Records
151
Agent score
79%

What's inside Hocuspocus

  1. Use @hocuspocus/transformer to convert Y.js documents

    main
    @hocuspocus/transformer is a utility for converting Y.js documents to and from Tiptap / ProseMirror JSON and HTML formats. This is particularly useful for server-side operations where you need to process or render collaborative document state outside of a live editor environment, such as generating document previews, performing exports, or preparing webhook payloads.
  2. Configure Webhook events and debounce settings

    main

    The Webhook extension allows you to subscribe to specific lifecycle events using the Events enum.

    Available events include:

    • Events.onChange: Triggered on document changes. These events are debounced by default to prevent excessive requests. You can tune this using debounce and debounceMaxWait options.
    • Events.onConnect: Triggered when a client connects.
    • Events.onDisconnect: Triggered when a client disconnects.
    • Events.onCreate: Triggered when a document is created.

    To verify the authenticity of incoming requests, use the secret provided during setup to check the X-Hocuspocus-Signature-256 header, which contains an HMAC-SHA256 signature.

  3. Understand the role of @hocuspocus/common

    main

    @hocuspocus/common is a utility package containing shared types, common enums, and helpers for the message/sync protocol used across the Hocuspocus ecosystem.

    Note for developers: This package is primarily an internal building block. Most end-users should instead depend on @hocuspocus/server or @hocuspocus/provider to interact with the Hocuspocus ecosystem. You should only depend on @hocuspocus/common directly if you are building custom extensions or low-level protocol implementations that require specific shared types.

  4. Scale Hocuspocus horizontally with S3 and Redis

    main

    To scale Hocuspocus horizontally, combine the S3 extension with the Redis extension. In this architecture, Redis handles real-time synchronization between server instances, while S3 provides the persistent storage layer for the documents.

    import { Server } from '@hocuspocus/server'
    import { Logger } from '@hocuspocus/extension-logger'
    import { Redis } from '@hocuspocus/extension-redis'
    import { S3 } from '@hocuspocus/extension-s3'
    
    const server1 = new Server({
      name: "server-1",
      port: 8001,
      extensions: [
        new Logger(),
        new Redis({
          host: "127.0.0.1",
          port: 6379,
        }),
        new S3({
          bucket: 'hocuspocus-documents',
          endpoint: 'http://localhost:9000',
          forcePathStyle: true,
          credentials: {
            accessKeyId: 'minioadmin',
            secretAccessKey: 'minioadmin'
          }
        }),
      ],
    })
    
    // Server 2 must have the same Redis and S3 configuration to sync correctly
    const server2 = new Server({
      name: "server-2", 
      port: 8002,
      extensions: [/* same extensions as server1 */],
    })
    
    server1.listen()
    server2.listen()
  5. Quickstart: Start a Hocuspocus WebSocket server

    main

    To start a Hocuspocus WebSocket server, import the Server class from @hocuspocus/server. You can configure the server by passing an options object to the constructor, which allows you to define the port, lifecycle hooks like onConnect, and extensions (such as @hocuspocus/extension-sqlite for persistence). Call .listen() to start the server. By default, the server listens on http://127.0.0.1 (or ws://127.0.0.1 for WebSocket connections).

    import { Server } from '@hocuspocus/server'
    import { SQLite } from '@hocuspocus/extension-sqlite'
    
    const server = new Server({
      port: 1234,
    
      async onConnect() {
        console.log('🔮')
      },
    
      extensions: [
        new SQLite({
          database: 'db.sqlite',
        }),
      ],
    });
    
    server.listen();
  6. Scale Hocuspocus horizontally with Redis

    main

    To scale Hocuspocus across multiple server instances, point every instance to the same Redis server. This allows document updates and awareness to be broadcasted via Redis pub/sub, ensuring clients connected to different instances stay in sync.

    Note: Redis handles real-time synchronization between instances, but it does not handle long-term storage. You must still use a persistence extension (like @hocuspocus/extension-sqlite, @hocuspocus/extension-s3, or @hocuspocus/extension-database) to save documents to a database.

    import { Server } from "@hocuspocus/server"
    import { Redis } from "@hocuspocus/extension-redis"
    
    const server = new Server({
      port: 1234,
      extensions: [
        new Redis({
          host: "127.0.0.1",
          port: 6379,
        }),
      ],
    })
    
    server.listen()