Skip to content

Commit 0083f50

Browse files
docs: Update Liveblocks (#1557)
* update liveblocks in lockfile * Added example * Added explicit hocuspocus dep to fix build * Updated package lock * Updated docs * Implemented feedback * Updated API key * Updated liveblocks * Added type cast --------- Co-authored-by: yousefed <[email protected]>
1 parent 3e52fde commit 0083f50

File tree

15 files changed

+2782
-618
lines changed

15 files changed

+2782
-618
lines changed

docs/pages/docs/collaboration/real-time-collaboration.mdx

+7-3
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,10 @@ When a user edits the document, an incremental change (or "update") is captured
6767

6868
## Liveblocks
6969

70-
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.
70+
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):
7171

7272
```shell
73-
npx create-liveblocks-app@latest --example nextjs-yjs-blocknote-advanced
73+
npx create-liveblocks-app@latest --example nextjs-blocknote --api-key
7474
```
7575

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

83-
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).
83+
You can also try the same example in a [live demo](https://liveblocks.io/examples/collaborative-text-editor/nextjs-blocknote).
84+
85+
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).
86+
87+
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).
8488

8589
## Partykit
8690

Binary file not shown.

examples/07-collaboration/02-liveblocks/.bnexample.json

+10-4
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,17 @@
22
"playground": true,
33
"docs": true,
44
"author": "yousefed",
5-
"tags": ["Advanced", "Saving/Loading", "Collaboration"],
5+
"tags": [
6+
"Advanced",
7+
"Saving/Loading",
8+
"Collaboration"
9+
],
610
"dependencies": {
7-
"@liveblocks/client": "^1.10.0",
8-
"@liveblocks/react": "^1.10.0",
9-
"@liveblocks/yjs": "^1.10.0",
11+
"@liveblocks/client": "^2.22.3",
12+
"@liveblocks/react": "^2.22.3",
13+
"@liveblocks/react-blocknote": "^2.22.3",
14+
"@liveblocks/react-tiptap": "^2.22.3",
15+
"@liveblocks/react-ui": "^2.22.3",
1016
"yjs": "^13.6.15"
1117
}
1218
}
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,29 @@
1-
import "@blocknote/core/fonts/inter.css";
2-
import { BlockNoteView } from "@blocknote/mantine";
3-
import "@blocknote/mantine/style.css";
4-
import { useCreateBlockNote } from "@blocknote/react";
5-
import { createClient } from "@liveblocks/client";
6-
import LiveblocksProvider from "@liveblocks/yjs";
7-
import * as Y from "yjs";
1+
// See https://liveblocks.io/docs/get-started/react-blocknote to see how this
2+
// example was created, and an explanation for all the code.
3+
import {
4+
ClientSideSuspense,
5+
LiveblocksProvider,
6+
RoomProvider,
7+
} from "@liveblocks/react/suspense";
8+
import "@liveblocks/react-ui/styles.css";
9+
import "@liveblocks/react-ui/styles/dark/media-query.css";
10+
import "@liveblocks/react-tiptap/styles.css";
811

9-
// Sets up Liveblocks client.
10-
const client = createClient({
11-
publicApiKey:
12-
"pk_dev_lJAS4XHx3l1e0x_Gh9VMtrvo8PEB1vrNarC2YRtAOp4t6i9_QAcSX2U953GS6v7B",
13-
});
14-
// Enters a multiplayer room.
15-
// Use a unique name as a "room" for your application.
16-
const { room } = client.enterRoom("your-project-name", {
17-
initialPresence: {},
18-
});
19-
20-
// Sets up Yjs document and Liveblocks Yjs provider.
21-
const doc = new Y.Doc();
22-
const provider = new LiveblocksProvider(room, doc);
12+
import { Editor } from "./Editor.js";
13+
import "./globals.css";
14+
import "./styles.css";
2315

2416
export default function App() {
25-
const editor = useCreateBlockNote({
26-
collaboration: {
27-
// The Yjs Provider responsible for transporting updates:
28-
provider,
29-
// Where to store BlockNote data in the Y.Doc:
30-
fragment: doc.getXmlFragment("document-store"),
31-
// Information (name and color) for this user:
32-
user: {
33-
name: "My Username",
34-
color: "#ff0000",
35-
},
36-
},
37-
});
38-
39-
// Renders the editor instance.
40-
return <BlockNoteView editor={editor} />;
17+
return (
18+
<LiveblocksProvider
19+
publicApiKey={
20+
"pk_prod_6iVYNrHvG98GvWioAutXrhTkpG0iQLrzUK3nfWT4_VKWl6NIrlt112YD29to9gQH"
21+
}>
22+
<RoomProvider id="my-room">
23+
<ClientSideSuspense fallback={<div>Loading…</div>}>
24+
<Editor />
25+
</ClientSideSuspense>
26+
</RoomProvider>
27+
</LiveblocksProvider>
28+
);
4129
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import "@blocknote/core/fonts/inter.css";
2+
import { BlockNoteEditor } from "@blocknote/core";
3+
import { BlockNoteView } from "@blocknote/mantine";
4+
import "@blocknote/mantine/style.css";
5+
import { useCreateBlockNoteWithLiveblocks } from "@liveblocks/react-blocknote";
6+
7+
import { Threads } from "./Threads.js";
8+
9+
export function Editor() {
10+
const editor = useCreateBlockNoteWithLiveblocks(
11+
{},
12+
{ mentions: true }
13+
) as BlockNoteEditor;
14+
15+
return (
16+
<div>
17+
<BlockNoteView editor={editor} className="editor" />
18+
<Threads editor={editor} />
19+
</div>
20+
);
21+
}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,25 @@
11
# Collaborative Editing with Liveblocks
22

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

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

715
**Relevant Docs:**
816

917
- [Editor Setup](/docs/editor-basics/setup)
1018
- [Liveblocks](/docs/collaboration/real-time-collaboration#liveblocks)
19+
20+
**From Liveblocks Website:**
21+
22+
- [Get Started with BlockNote](https://liveblocks.io/docs/get-started/react-blocknote)
23+
- [Ready Made Features](https://liveblocks.io/docs/ready-made-features/text-editor/blocknote)
24+
- [API Reference](https://liveblocks.io/docs/api-reference/liveblocks-react-blocknote)
25+
- [Advanced Example](https://liveblocks.io/examples/collaborative-text-editor/nextjs-blocknote)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { BlockNoteEditor } from "@blocknote/core";
2+
import { useThreads } from "@liveblocks/react/suspense";
3+
import {
4+
AnchoredThreads,
5+
FloatingComposer,
6+
FloatingThreads,
7+
} from "@liveblocks/react-blocknote";
8+
9+
export function Threads({ editor }: { editor: BlockNoteEditor | null }) {
10+
const { threads } = useThreads({ query: { resolved: false } });
11+
12+
if (!editor) {
13+
return null;
14+
}
15+
16+
return (
17+
<>
18+
<div className="anchored-threads">
19+
<AnchoredThreads editor={editor} threads={threads} />
20+
</div>
21+
<FloatingThreads
22+
editor={editor}
23+
threads={threads}
24+
className="floating-threads"
25+
/>
26+
<FloatingComposer editor={editor} className="floating-composer" />
27+
</>
28+
);
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
html {
2+
font-family: Inter, sans-serif;
3+
background: #f9f9f9;
4+
}
5+
6+
@media (prefers-color-scheme: dark) {
7+
html {
8+
background: #0c0c0c;
9+
}
10+
}
11+
12+
.editor {
13+
position: absolute;
14+
inset: 0;
15+
max-width: 1024px;
16+
margin: 0 auto;
17+
padding: 48px 0;
18+
}
19+
20+
.bn-editor {
21+
padding: 36px 52px;
22+
min-height: 100%;
23+
}
24+
25+
/* For mobile */
26+
.floating-threads {
27+
display: none;
28+
}
29+
30+
/* For desktop */
31+
.anchored-threads {
32+
display: block;
33+
max-width: 300px;
34+
width: 100%;
35+
position: absolute;
36+
right: 12px;
37+
}
38+
39+
@media (max-width: 640px) {
40+
.floating-threads {
41+
display: block;
42+
}
43+
44+
.anchored-threads {
45+
display: none;
46+
}
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Define Liveblocks types for your application
2+
// https://liveblocks.io/docs/api-reference/liveblocks-react#Typing-your-data
3+
declare global {
4+
interface Liveblocks {
5+
// Each user's Presence, for useMyPresence, useOthers, etc.
6+
Presence: {
7+
// Example, real-time cursor coordinates
8+
// cursor: { x: number; y: number };
9+
};
10+
11+
// The Storage tree for the room, for useMutation, useStorage, etc.
12+
Storage: {
13+
// Example, a conflict-free list
14+
// animals: LiveList<string>;
15+
};
16+
17+
// Custom user info set when authenticating with a secret key
18+
UserMeta: {
19+
id: string;
20+
info: {
21+
// Example properties, for useSelf, useUser, useOthers, etc.
22+
// name: string;
23+
// avatar: string;
24+
};
25+
};
26+
27+
// Custom events, for useBroadcastEvent, useEventListener
28+
RoomEvent: {};
29+
// Example has two events, using a union
30+
// | { type: "PLAY" }
31+
// | { type: "REACTION"; emoji: "🔥" };
32+
33+
// Custom metadata set on threads, for useThreads, useCreateThread, etc.
34+
ThreadMetadata: {
35+
// Example, attaching coordinates to a thread
36+
// x: number;
37+
// y: number;
38+
};
39+
40+
// Custom room info set with resolveRoomsInfo, for useRoomInfo
41+
RoomInfo: {
42+
// Example, rooms with a title and url
43+
// title: string;
44+
// url: string;
45+
};
46+
}
47+
}
48+
49+
export {};

examples/07-collaboration/02-liveblocks/package.json

+5-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818
"@blocknote/shadcn": "latest",
1919
"react": "^18.3.1",
2020
"react-dom": "^18.3.1",
21-
"@liveblocks/client": "^1.10.0",
22-
"@liveblocks/react": "^1.10.0",
23-
"@liveblocks/yjs": "^1.10.0",
21+
"@liveblocks/client": "^2.22.0",
22+
"@liveblocks/react": "^2.22.0",
23+
"@liveblocks/react-blocknote": "^2.22.0",
24+
"@liveblocks/react-tiptap": "^2.22.0",
25+
"@liveblocks/react-ui": "^2.22.0",
2426
"yjs": "^13.6.15"
2527
},
2628
"devDependencies": {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.editor {
2+
position: relative;
3+
height: 100%;
4+
}
5+
6+
div:has(> .editor) {
7+
height: 100%;
8+
}

0 commit comments

Comments
 (0)