DEV Community

Alex Spinov
Alex Spinov

Posted on

Liveblocks Has a Free API — Here's How to Add Real-Time Collaboration to Any App

A dev team I know spent 3 months building real-time collaboration from scratch. WebSocket server, conflict resolution, presence tracking, undo/redo. Then they found Liveblocks — they replaced 8,000 lines of code with 200.

What Liveblocks Offers for Free

Liveblocks free tier:

  • Up to 200 monthly active users
  • Real-time presence — see who's online, cursor positions
  • Conflict-free data — CRDT-based storage
  • Room-based architecture — isolated collaborative spaces
  • Comments — threaded discussions on any element
  • Notifications — in-app notification system
  • React, Vue, and vanilla JS support

Quick Start

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'
});

export const { RoomProvider, useOthers, useMyPresence, useStorage, useMutation } = createRoomContext(client);
Enter fullscreen mode Exit fullscreen mode

Real-Time Cursors

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

function App() {
  return (
    <RoomProvider id="my-room" initialPresence={{ cursor: null }}>
      <Canvas />
    </RoomProvider>
  );
}

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

  return (
    <div
      style={{ width: '100vw', height: '100vh', position: 'relative' }}
      onPointerMove={(e) => {
        updateMyPresence({ cursor: { x: e.clientX, y: e.clientY } });
      }}
      onPointerLeave={() => updateMyPresence({ cursor: null })}
    >
      {others.map(({ connectionId, presence }) => {
        if (!presence.cursor) return null;
        return (
          <div
            key={connectionId}
            style={{
              position: 'absolute',
              left: presence.cursor.x,
              top: presence.cursor.y,
              width: 8,
              height: 8,
              borderRadius: '50%',
              background: `hsl(${connectionId * 50}, 70%, 50%)`
            }}
          />
        );
      })}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Collaborative Storage (CRDT)

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

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

  const addTodo = useMutation(({ storage }, text) => {
    storage.get('todos').push({ text, done: false, id: Date.now() });
  }, []);

  const toggleTodo = useMutation(({ storage }, index) => {
    const todo = storage.get('todos').get(index);
    todo.set('done', !todo.get('done'));
  }, []);

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

REST API

# Get active users in a room
curl 'https://api.liveblocks.io/v2/rooms/my-room/active_users' \
  -H 'Authorization: Bearer sk_YOUR_SECRET_KEY'

# Get storage data
curl 'https://api.liveblocks.io/v2/rooms/my-room/storage' \
  -H 'Authorization: Bearer sk_YOUR_SECRET_KEY'

# Initialize room storage
curl -X POST 'https://api.liveblocks.io/v2/rooms/my-room/storage' \
  -H 'Authorization: Bearer sk_YOUR_SECRET_KEY' \
  -H 'Content-Type: application/json' \
  -d '{ "liveblocksType": "LiveObject", "data": { "todos": { "liveblocksType": "LiveList", "data": [] } } }'
Enter fullscreen mode Exit fullscreen mode

Use Cases

  • Collaborative editors — Notion-like docs, spreadsheets
  • Design tools — Figma-like multiplayer canvas
  • Whiteboards — Miro-like collaborative boards
  • Project management — Real-time kanban boards
  • Forms — Multi-user form filling

Need real-time data from the web? Check out my web scraping actors on Apify — automated data collection.

Building a collaborative app? Email me at spinov001@gmail.com.

Top comments (0)