From 859ea82975a17dc18bb5bd6f1da7034168383e46 Mon Sep 17 00:00:00 2001 From: Chris Nicholas Date: Wed, 3 Jun 2026 14:20:24 +0100 Subject: [PATCH] Better Storage get started guides (#3506) --- docs/pages/get-started/nextjs.mdx | 135 ++++++++++++++++++++++++++++-- docs/pages/get-started/react.mdx | 134 +++++++++++++++++++++++++++-- 2 files changed, 253 insertions(+), 16 deletions(-) diff --git a/docs/pages/get-started/nextjs.mdx b/docs/pages/get-started/nextjs.mdx index 24456dfad82..75bcf9150a9 100644 --- a/docs/pages/get-started/nextjs.mdx +++ b/docs/pages/get-started/nextjs.mdx @@ -109,25 +109,144 @@ the [`@liveblocks/react`](/docs/api-reference/liveblocks-react) package. - Use the Liveblocks hooks + Create a multiplayer input - Now that we’re connected to a room, we can start using the Liveblocks hooks. - The first we’ll add is [`useOthers`](/docs/api-reference/liveblocks-react#useOthers), a hook that provides information - about which other users are connected to the room. + From this point, you can use Liveblocks hooks to create your multiplayer app. For example, you can create + a shared input that stays in sync across users. To set it up, first [define your storage + type](/docs/api-reference/liveblocks-client#Typing-your-data) in `liveblocks.config.ts`. An `input` [`LiveObject`](/docs/api-reference/liveblocks-client#LiveObject) + can store the text of the input. + + ```ts file="liveblocks.config.ts" + import { LiveObject } from "@liveblocks/client"; + + declare global { + interface Liveblocks { + // +++ + Storage: { + input: LiveObject<{ text: string }>; + }; + // +++ + } + } + + export {}; + ``` + + Next, set an initial value for `input` on [`RoomProvider`](/docs/api-reference/liveblocks-react#RoomProvider), + a new `LiveObject` with a `text` value. - ```tsx file="app/CollaborativeApp.tsx" highlight="6" + ```tsx file="app/Room.tsx" "use client"; - import { useOthers } from "@liveblocks/react/suspense"; + import { ReactNode } from "react"; + import { LiveObject } from "@liveblocks/client"; + import { + LiveblocksProvider, + RoomProvider, + ClientSideSuspense, + } from "@liveblocks/react/suspense"; + + export function Room({ children }: { children: ReactNode }) { + return ( + + + Loading…}> + {children} + + + + ); + } + ``` + + Now, use [`useStorage`](/docs/api-reference/liveblocks-react#useStorage) to read the value of `input.text` and + [`useMutation`](/docs/api-reference/liveblocks-react#useMutation) to update it. + + ```tsx file="app/CollaborativeApp.tsx" + "use client"; + + import { useStorage, useMutation } from "@liveblocks/react/suspense"; export function CollaborativeApp() { + // +++ + const text = useStorage((root) => root.input.text); + // +++ + + // +++ + const updateText = useMutation(({ storage }, newText: string) => { + const input = storage.get("input"); + input.set("text", newText); + }, []); + // +++ + + return ( + updateText(e.target.value)} + // +++ + placeholder="Start typing…" + /> + ); + } + ``` + + Open your app in two browser tabs to see the input update in realtime. + + + + + + Show custom presence + + + [`useOthers`](/docs/api-reference/liveblocks-react#useOthers) allows you to + access a list of users that are currently connected to the room. Build a + simple avatar stack from the list of connected users. + + ```tsx file="app/Avatars.tsx" + "use client"; + + import { useOthers } from "@liveblocks/react/suspense"; + + export function Avatars() { + // +++ const others = useOthers(); - const userCount = others.length; - return
There are {userCount} other user(s) online
; + // +++ + + return ( +
+ // +++ + {others.map(({ connectionId }, index) => ( + // +++ + + ))} +
+ ); } ``` + Open your app in two browser tabs to see avatars appear for each user. +
diff --git a/docs/pages/get-started/react.mdx b/docs/pages/get-started/react.mdx index 6de277eec39..48c08431664 100644 --- a/docs/pages/get-started/react.mdx +++ b/docs/pages/get-started/react.mdx @@ -106,26 +106,144 @@ collaboration to your React application using the hooks from the - Use the Liveblocks hooks + Create a multiplayer input - Now that we’re connected to a room, we can start using the Liveblocks hooks. - The first we’ll add is [`useOthers`](/docs/api-reference/liveblocks-react#useOthers), a hook that provides information about - which other users are connected to the room. + From this point, you can use Liveblocks hooks to create your multiplayer app. For example, you can create + a shared input that stays in sync across users. To set it up, first [define your storage + type](/docs/api-reference/liveblocks-client#Typing-your-data) in `liveblocks.config.ts`. An `input` [`LiveObject`](/docs/api-reference/liveblocks-client#LiveObject) + can store the text of the input. + + ```ts file="liveblocks.config.ts" + import { LiveObject } from "@liveblocks/client"; + + declare global { + interface Liveblocks { + // +++ + Storage: { + input: LiveObject<{ text: string }>; + }; + // +++ + } + } + + export {}; + ``` - ```tsx file="Room.tsx" highlight="6" + Next, set an initial value for `input` on [`RoomProvider`](/docs/api-reference/liveblocks-react#RoomProvider), + a new `LiveObject` with a `text` value. + + ```tsx file="App.tsx" "use client"; - import { useOthers } from "./liveblocks.config"; + import { LiveObject } from "@liveblocks/client"; + import { + LiveblocksProvider, + RoomProvider, + ClientSideSuspense, + } from "@liveblocks/react/suspense"; + import { Room } from "./Room"; + + export default function App() { + return ( + + + Loading…}> + + + + + ); + } + ``` + + Now, use [`useStorage`](/docs/api-reference/liveblocks-react#useStorage) to read the value of `input.text` and + [`useMutation`](/docs/api-reference/liveblocks-react#useMutation) to update it. + + ```tsx file="Room.tsx" + "use client"; + + import { useStorage, useMutation } from "@liveblocks/react/suspense"; export function Room() { + // +++ + const text = useStorage((root) => root.input.text); + // +++ + + // +++ + const updateText = useMutation(({ storage }, newText: string) => { + const input = storage.get("input"); + input.set("text", newText); + }, []); + // +++ + + return ( + updateText(e.target.value)} + // +++ + placeholder="Start typing…" + /> + ); + } + ``` + + Open your app in two browser tabs to see the input update in realtime. + + + + + + Show custom presence + + + [`useOthers`](/docs/api-reference/liveblocks-react#useOthers) allows you to + access a list of users that are currently connected to the room. Build a + simple avatar stack from the list of connected users. + + ```tsx file="Avatars.tsx" + "use client"; + + import { useOthers } from "@liveblocks/react/suspense"; + + export function Avatars() { + // +++ const others = useOthers(); - const userCount = others.length; + // +++ - return
There are {userCount} other user(s) online
; + return ( +
+ // +++ + {others.map(({ connectionId }, index) => ( + // +++ + + ))} +
+ ); } ``` + Open your app in two browser tabs to see avatars appear for each user. +