Skip to content

docs: Update Liveblocks #1557

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Apr 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions docs/pages/docs/collaboration/real-time-collaboration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ When a user edits the document, an incremental change (or "update") is captured

## Liveblocks

Liveblocks provides a hosted back-end for Yjs which allows you to download and set up a real-time multiplayer BlockNote example with one command.
Liveblocks provides a hosted back-end for Yjs. You can create a fully-featured example project which uses Liveblocks with BlockNote by running the command below (you will need a Liveblocks account for this):

```shell
npx create-liveblocks-app@latest --example nextjs-yjs-blocknote-advanced
npx create-liveblocks-app@latest --example nextjs-blocknote --api-key
```

<video
Expand All @@ -80,7 +80,11 @@ npx create-liveblocks-app@latest --example nextjs-yjs-blocknote-advanced
aria-label="BlockNote example using Liveblocks Yjs, showing collaboration and DevTools"
/>

You can also try the same example in a [live demo](https://liveblocks.io/examples/collaborative-text-editor-advanced/nextjs-yjs-blocknote-advanced). To start with Liveblocks and BlockNote make sure to follow their [getting started guide](https://liveblocks.io/docs/get-started/yjs-blocknote-react).
You can also try the same example in a [live demo](https://liveblocks.io/examples/collaborative-text-editor/nextjs-blocknote).

For a simpler demo, check out [this example](/docs/examples/collaboration/liveblocks), which follows their [getting started guide](https://liveblocks.io/docs/get-started/react-blocknote).

If you want more info on integrating Liveblocks, take a look at their [ready-made features for BlockNote](https://liveblocks.io/docs/ready-made-features/text-editor/blocknote) and [API reference](https://liveblocks.io/docs/api-reference/liveblocks-react-blocknote#AnchoredThreads).

## Partykit

Expand Down
Binary file modified docs/public/img/screenshots/liveblocks_blocknote_example.mp4
Binary file not shown.
14 changes: 10 additions & 4 deletions examples/07-collaboration/02-liveblocks/.bnexample.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@
"playground": true,
"docs": true,
"author": "yousefed",
"tags": ["Advanced", "Saving/Loading", "Collaboration"],
"tags": [
"Advanced",
"Saving/Loading",
"Collaboration"
],
"dependencies": {
"@liveblocks/client": "^1.10.0",
"@liveblocks/react": "^1.10.0",
"@liveblocks/yjs": "^1.10.0",
"@liveblocks/client": "^2.22.3",
"@liveblocks/react": "^2.22.3",
"@liveblocks/react-blocknote": "^2.22.3",
"@liveblocks/react-tiptap": "^2.22.3",
"@liveblocks/react-ui": "^2.22.3",
"yjs": "^13.6.15"
}
}
62 changes: 25 additions & 37 deletions examples/07-collaboration/02-liveblocks/App.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,29 @@
import "@blocknote/core/fonts/inter.css";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";
import { useCreateBlockNote } from "@blocknote/react";
import { createClient } from "@liveblocks/client";
import LiveblocksProvider from "@liveblocks/yjs";
import * as Y from "yjs";
// See https://liveblocks.io/docs/get-started/react-blocknote to see how this
// example was created, and an explanation for all the code.
import {
ClientSideSuspense,
LiveblocksProvider,
RoomProvider,
} from "@liveblocks/react/suspense";
import "@liveblocks/react-ui/styles.css";
import "@liveblocks/react-ui/styles/dark/media-query.css";
import "@liveblocks/react-tiptap/styles.css";

// Sets up Liveblocks client.
const client = createClient({
publicApiKey:
"pk_dev_lJAS4XHx3l1e0x_Gh9VMtrvo8PEB1vrNarC2YRtAOp4t6i9_QAcSX2U953GS6v7B",
});
// Enters a multiplayer room.
// Use a unique name as a "room" for your application.
const { room } = client.enterRoom("your-project-name", {
initialPresence: {},
});

// Sets up Yjs document and Liveblocks Yjs provider.
const doc = new Y.Doc();
const provider = new LiveblocksProvider(room, doc);
import { Editor } from "./Editor.js";
import "./globals.css";
import "./styles.css";

export default function App() {
const editor = useCreateBlockNote({
collaboration: {
// The Yjs Provider responsible for transporting updates:
provider,
// Where to store BlockNote data in the Y.Doc:
fragment: doc.getXmlFragment("document-store"),
// Information (name and color) for this user:
user: {
name: "My Username",
color: "#ff0000",
},
},
});

// Renders the editor instance.
return <BlockNoteView editor={editor} />;
return (
<LiveblocksProvider
publicApiKey={
"pk_prod_6iVYNrHvG98GvWioAutXrhTkpG0iQLrzUK3nfWT4_VKWl6NIrlt112YD29to9gQH"
}>
<RoomProvider id="my-room">
<ClientSideSuspense fallback={<div>Loading…</div>}>
<Editor />
</ClientSideSuspense>
</RoomProvider>
</LiveblocksProvider>
);
}
21 changes: 21 additions & 0 deletions examples/07-collaboration/02-liveblocks/Editor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import "@blocknote/core/fonts/inter.css";
import { BlockNoteEditor } from "@blocknote/core";
import { BlockNoteView } from "@blocknote/mantine";
import "@blocknote/mantine/style.css";
import { useCreateBlockNoteWithLiveblocks } from "@liveblocks/react-blocknote";

import { Threads } from "./Threads.js";

export function Editor() {
const editor = useCreateBlockNoteWithLiveblocks(
{},
{ mentions: true }
) as BlockNoteEditor;

return (
<div>
<BlockNoteView editor={editor} className="editor" />
<Threads editor={editor} />
</div>
);
}
19 changes: 17 additions & 2 deletions examples/07-collaboration/02-liveblocks/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
# Collaborative Editing with Liveblocks

In this example, we use Liveblocks to let multiple users collaborate on a single BlockNote document in real-time.
In this example, we use
the [Liveblocks + BlockNote setup guide](https://liveblocks.io/docs/get-started/react-blocknote)
to create a collaborative BlockNote editor, where multiple people can work on
the same document in real-time.

**Try it out:** Open this page in a new browser tab or window to see it in action!
Users can also add comments to the documents to start threads, which are
displayed next to the editor. As well as that, they can react to, reply to, and
resolve existing comments.

**Try it out:** Open this page in a new browser tab or window to see it in
action!

**Relevant Docs:**

- [Editor Setup](/docs/editor-basics/setup)
- [Liveblocks](/docs/collaboration/real-time-collaboration#liveblocks)

**From Liveblocks Website:**

- [Get Started with BlockNote](https://liveblocks.io/docs/get-started/react-blocknote)
- [Ready Made Features](https://liveblocks.io/docs/ready-made-features/text-editor/blocknote)
- [API Reference](https://liveblocks.io/docs/api-reference/liveblocks-react-blocknote)
- [Advanced Example](https://liveblocks.io/examples/collaborative-text-editor/nextjs-blocknote)
29 changes: 29 additions & 0 deletions examples/07-collaboration/02-liveblocks/Threads.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { BlockNoteEditor } from "@blocknote/core";
import { useThreads } from "@liveblocks/react/suspense";
import {
AnchoredThreads,
FloatingComposer,
FloatingThreads,
} from "@liveblocks/react-blocknote";

export function Threads({ editor }: { editor: BlockNoteEditor | null }) {
const { threads } = useThreads({ query: { resolved: false } });

if (!editor) {
return null;
}

return (
<>
<div className="anchored-threads">
<AnchoredThreads editor={editor} threads={threads} />
</div>
<FloatingThreads
editor={editor}
threads={threads}
className="floating-threads"
/>
<FloatingComposer editor={editor} className="floating-composer" />
</>
);
}
47 changes: 47 additions & 0 deletions examples/07-collaboration/02-liveblocks/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
html {
font-family: Inter, sans-serif;
background: #f9f9f9;
}

@media (prefers-color-scheme: dark) {
html {
background: #0c0c0c;
}
}

.editor {
position: absolute;
inset: 0;
max-width: 1024px;
margin: 0 auto;
padding: 48px 0;
}

.bn-editor {
padding: 36px 52px;
min-height: 100%;
}

/* For mobile */
.floating-threads {
display: none;
}

/* For desktop */
.anchored-threads {
display: block;
max-width: 300px;
width: 100%;
position: absolute;
right: 12px;
}

@media (max-width: 640px) {
.floating-threads {
display: block;
}

.anchored-threads {
display: none;
}
}
49 changes: 49 additions & 0 deletions examples/07-collaboration/02-liveblocks/liveblocks.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Define Liveblocks types for your application
// https://liveblocks.io/docs/api-reference/liveblocks-react#Typing-your-data
declare global {
interface Liveblocks {
// Each user's Presence, for useMyPresence, useOthers, etc.
Presence: {
// Example, real-time cursor coordinates
// cursor: { x: number; y: number };
};

// The Storage tree for the room, for useMutation, useStorage, etc.
Storage: {
// Example, a conflict-free list
// animals: LiveList<string>;
};

// Custom user info set when authenticating with a secret key
UserMeta: {
id: string;
info: {
// Example properties, for useSelf, useUser, useOthers, etc.
// name: string;
// avatar: string;
};
};

// Custom events, for useBroadcastEvent, useEventListener
RoomEvent: {};
// Example has two events, using a union
// | { type: "PLAY" }
// | { type: "REACTION"; emoji: "🔥" };

// Custom metadata set on threads, for useThreads, useCreateThread, etc.
ThreadMetadata: {
// Example, attaching coordinates to a thread
// x: number;
// y: number;
};

// Custom room info set with resolveRoomsInfo, for useRoomInfo
RoomInfo: {
// Example, rooms with a title and url
// title: string;
// url: string;
};
}
}

export {};
8 changes: 5 additions & 3 deletions examples/07-collaboration/02-liveblocks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
"@blocknote/shadcn": "latest",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"@liveblocks/client": "^1.10.0",
"@liveblocks/react": "^1.10.0",
"@liveblocks/yjs": "^1.10.0",
"@liveblocks/client": "^2.22.0",
"@liveblocks/react": "^2.22.0",
"@liveblocks/react-blocknote": "^2.22.0",
"@liveblocks/react-tiptap": "^2.22.0",
"@liveblocks/react-ui": "^2.22.0",
"yjs": "^13.6.15"
},
"devDependencies": {
Expand Down
8 changes: 8 additions & 0 deletions examples/07-collaboration/02-liveblocks/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.editor {
position: relative;
height: 100%;
}

div:has(> .editor) {
height: 100%;
}
Loading
Loading