DEV Community

Alex Spinov
Alex Spinov

Posted on

Liveblocks Has a Free API — Add Real-Time Collaboration to Any App

TL;DR

Liveblocks provides real-time collaboration infrastructure — presence, cursors, comments, and document storage. The free tier supports 1,000 monthly active users with all features included.

What Is Liveblocks?

Liveblocks provides collaboration primitives:

  • Presence — show who's online, cursor positions, selections
  • Storage — conflict-free real-time document syncing (CRDT)
  • Comments — threaded comments with mentions and notifications
  • Text Editor — collaborative rich text with Tiptap/Lexical
  • Notifications — in-app notification system
  • Free tier — 1,000 MAU, all features

Quick Start with React

npm install @liveblocks/client @liveblocks/react
Enter fullscreen mode Exit fullscreen mode
// liveblocks.config.ts
import { createClient } from "@liveblocks/client";
import { createRoomContext } from "@liveblocks/react";

const client = createClient({
  publicApiKey: "pk_YOUR_PUBLIC_KEY",
});

type Presence = {
  cursor: { x: number; y: number } | null;
  name: string;
};

export const { RoomProvider, useOthers, useMyPresence } =
  createRoomContext<Presence>(client);
Enter fullscreen mode Exit fullscreen mode

Live Cursors

import { RoomProvider, useOthers, useMyPresence } from "./liveblocks.config";

function Cursors() {
  const others = useOthers();
  const [myPresence, updateMyPresence] = useMyPresence();

  return (
    <div
      style={{ width: "100vw", height: "100vh" }}
      onPointerMove={(e) =>
        updateMyPresence({ cursor: { x: e.clientX, y: e.clientY } })
      }
      onPointerLeave={() => updateMyPresence({ cursor: null })}
    >
      {others.map(({ connectionId, presence }) =>
        presence.cursor ? (
          <div
            key={connectionId}
            style={{
              position: "absolute",
              left: presence.cursor.x,
              top: presence.cursor.y,
              width: 10,
              height: 10,
              borderRadius: "50%",
              background: "red",
            }}
          />
        ) : null
      )}
    </div>
  );
}

function App() {
  return (
    <RoomProvider id="my-room" initialPresence={{ cursor: null, name: "" }}>
      <Cursors />
    </RoomProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode

Real-Time Storage (CRDT)

import { useMutation, useStorage } from "./liveblocks.config";

function TodoList() {
  const todos = useStorage((root) => root.todos);

  const addTodo = useMutation(({ storage }, text: string) => {
    const todos = storage.get("todos");
    todos.push({ text, completed: false });
  }, []);

  const toggleTodo = useMutation(({ storage }, index: number) => {
    const todo = storage.get("todos").get(index);
    todo.set("completed", !todo.get("completed"));
  }, []);

  return (
    <div>
      {todos?.map((todo, i) => (
        <div key={i} onClick={() => toggleTodo(i)}>
          {todo.completed ? "" : ""} {todo.text}
        </div>
      ))}
      <button onClick={() => addTodo("New task")}>Add</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Comments

import { Thread, Composer } from "@liveblocks/react-comments";
import { useThreads } from "./liveblocks.config";

function Comments() {
  const { threads } = useThreads();

  return (
    <div>
      {threads.map((thread) => (
        <Thread key={thread.id} thread={thread} />
      ))}
      <Composer />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Liveblocks vs Alternatives

Feature Liveblocks PartyKit Socket.IO Firebase
Free MAU 1,000 Unlimited Self-host 100
Presence ✅ Built-in Manual Manual Manual
CRDT Storage Y.js
Comments
Notifications ✅ FCM
React hooks

Resources


Building collaborative data tools? My Apify scraping tools extract web data at scale — combine with Liveblocks for real-time collaborative data analysis. Questions? Email spinov001@gmail.com

Top comments (0)