diff --git a/docs/pages/get-started/nextjs-ai-notifications.mdx b/docs/pages/get-started/nextjs-ai-notifications.mdx
new file mode 100644
index 0000000000..5d1ff69b68
--- /dev/null
+++ b/docs/pages/get-started/nextjs-ai-notifications.mdx
@@ -0,0 +1,378 @@
+---
+meta:
+ title: "Get started with AI agent notifications using Liveblocks and Next.js"
+ parentTitle: "Quickstart"
+ description:
+ "Learn how to notify users when an AI agent has completed its work using
+ Liveblocks notifications and Next.js"
+---
+
+Liveblocks is a realtime collaboration infrastructure for building performant
+collaborative experiences. Follow this guide to create an inbox notification
+system in your app, and notify users when an AI agent has completed its work.
+This uses a Next.js `/app` directory application, with the hooks from
+[`@liveblocks/react`](/docs/api-reference/liveblocks-react), the components from
+[`@liveblocks/react-ui`](/docs/api-reference/liveblocks-react-ui), and
+[`@liveblocks/node`](/docs/api-reference/liveblocks-node) on the server.
+
+## Quickstart
+
+
+
+
+
+ Install Liveblocks
+
+
+ Every package should use the same version.
+
+ ```bash trackEvent="install_liveblocks"
+ npm install @liveblocks/client @liveblocks/react @liveblocks/react-ui @liveblocks/node
+ ```
+
+
+
+
+
+ Initialize the `liveblocks.config.ts` file
+
+
+ We can use this file later to [define types for our application](/docs/api-reference/liveblocks-react#Typing-your-data).
+
+ ```bash
+ npx create-liveblocks-app@latest --init --framework react
+ ```
+
+
+
+
+
+ Add your secret key
+
+
+ Create a `.env.local` file and add your Liveblocks secret key from the
+ [dashboard](/dashboard/apikeys).
+
+ ```env file=".env.local"
+ LIVEBLOCKS_SECRET_KEY="{{SECRET_KEY}}"
+ ```
+
+
+
+
+
+ Set up authentication
+
+
+ Create an [authentication](/docs/authentication) API route with
+ [`identifyUser`](/docs/api-reference/liveblocks-node#id-tokens),
+ passing a unique user ID.
+
+ ```ts file="app/api/liveblocks-auth/route.ts"
+ import { Liveblocks } from "@liveblocks/node";
+
+ const liveblocks = new Liveblocks({
+ secret: process.env.LIVEBLOCKS_SECRET_KEY!,
+ });
+
+ export async function POST(request: Request) {
+ // Get the current user from your database
+ const user = __getUserFromDB__(request);
+
+ // Identify the user and return the result
+ const { status, body } = await liveblocks.identifyUser(
+ { userId: user.id },
+ {
+ userInfo: {
+ name: user.name,
+ avatar: user.avatar,
+ },
+ },
+ );
+
+ return new Response(body, { status });
+ }
+ ```
+
+
+
+
+
+ Create a Liveblocks provider
+
+
+ Liveblocks Notifications uses the concept of projects, which relate to
+ projects in [your dashboard](/dashboard). Notifications are sent between
+ users in the same project. To connect and receive notifications, you must
+ add [`LiveblocksProvider`](/docs/api-reference/liveblocks-react#LiveblocksProvider)
+ to a client component in your app.
+
+ ```tsx file="app/Providers.tsx" highlight="8-10"
+ "use client";
+
+ import { ReactNode } from "react";
+ import { LiveblocksProvider } from "@liveblocks/react";
+
+ export function Providers({ children }: { children: ReactNode }) {
+ return (
+
+ {children}
+
+ );
+ }
+ ```
+
+
+
+
+
+ Add the provider to your layout
+
+
+ After creating your provider file, it’s time to use it. Import
+ your room into your `layout.tsx` file.
+
+ ```tsx file="app/layout.tsx"
+ import { Providers } from "./Providers";
+
+ export default function Layout({ children }) {
+ return (
+
+
+ // +++
+
+ {children}
+
+ // +++
+
+
+ );
+ }
+ ```
+
+
+
+
+
+ Use the Liveblocks hooks and components
+
+
+ Now that we’ve set up the provider, we can start using the Liveblocks hooks and components.
+ We’ll add [`useInboxNotifications`](/docs/api-reference/liveblocks-react#useInboxNotifications)
+ to get the current project’s notifications, then we’ll
+ use [`InboxNotification`](/docs/api-reference/liveblocks-react-ui#InboxNotification) and [`InboxNotificationList`](/docs/api-reference/liveblocks-react-ui#InboxNotificationList) to render them.
+
+ ```tsx file="app/page.tsx" highlight="10,13-20"
+ "use client";
+
+ import { useInboxNotifications } from "@liveblocks/react/suspense";
+ import {
+ InboxNotification,
+ InboxNotificationList,
+ } from "@liveblocks/react-ui";
+
+ export default function Page() {
+ const { inboxNotifications } = useInboxNotifications();
+
+ return (
+
+ {inboxNotifications.map((inboxNotification) => (
+
+ ))}
+
+ );
+ }
+ ```
+
+
+
+
+
+ Import default styles
+
+
+ The default components come with default styles, you can import them into the
+ root layout of your app or directly into a CSS file with `@import`.
+
+ ```tsx file="app/layout.tsx"
+ import "@liveblocks/react-ui/styles.css";
+ ```
+
+
+
+
+
+
+ Notify the user when your agent completes
+
+
+ Trigger a notification with
+ [`triggerInboxNotification`](/docs/api-reference/liveblocks-node#post-inbox-notifications-trigger)
+ from a server action or route handler at the end of your agent’s work. In
+ this example, a custom `$agentCompleted` notification is sent once the
+ agent has finished a task.
+
+ ```ts file="app/run-agent.ts"
+ "use server";
+
+ import { Liveblocks } from "@liveblocks/node";
+
+ const liveblocks = new Liveblocks({
+ secret: process.env.LIVEBLOCKS_SECRET_KEY!,
+ });
+
+ export async function runAgent({
+ userId,
+ task,
+ }: {
+ userId: string;
+ task: string;
+ }) {
+ const startedAt = Date.now();
+
+ // Run your AI agent here, e.g. generateText, mutateFlow, …
+ await __runYourAgent__({ task });
+
+ // +++
+ // Notify the user that the agent has finished
+ await liveblocks.triggerInboxNotification({
+ userId,
+ kind: "$agentCompleted",
+ subjectId: `agent-${task}`,
+ activityData: {
+ task,
+ status: "complete",
+ durationMs: Date.now() - startedAt,
+ },
+ });
+ // +++
+ }
+ ```
+
+
+
+
+
+
+
+ Render the agent notification
+
+
+ After triggering the custom notification, modify `InboxNotification` to
+ [render `$agentCompleted` with custom UI](/docs/api-reference/liveblocks-react-ui#Rendering-notification-kinds-differently).
+
+ ```tsx file="app/page.tsx"
+ "use client";
+
+ import { useInboxNotifications } from "@liveblocks/react/suspense";
+ import {
+ InboxNotification,
+ InboxNotificationList,
+ } from "@liveblocks/react-ui";
+
+ export default function Page() {
+ const { inboxNotifications } = useInboxNotifications();
+
+ return (
+
+ {inboxNotifications.map((inboxNotification) => (
+ (
+ ✨}
+ >
+ Your agent finished working on{" "}
+ {props.inboxNotification.activities[0].data.task}.
+
+ ),
+ }}
+ // +++
+ />
+ ))}
+
+ );
+ }
+ ```
+
+
+
+
+
+
+ Next: add your users
+
+
+ Notifications is set up and working now, but the auth route is using a placeholder
+ user—the next step is to connect it to your real users, and attach their name and avatar to their notifications.
+
+
+
+
+
+
+
+## What to read next
+
+Congratulations! You’ve set up notifications that fire when your AI agent
+finishes its work.
+
+- [API reference](/docs/api-reference/liveblocks-react#Notifications)
+- [Component reference](/docs/api-reference/liveblocks-react-ui#Notifications)
+- [`triggerInboxNotification` reference](/docs/api-reference/liveblocks-node#post-inbox-notifications-trigger)
+- [AI Presence quickstart](/docs/get-started/nextjs-ai-presence)
+
+---
+
+## Examples using Notifications
+
+
+
+
+
+
+
diff --git a/docs/pages/get-started/nextjs-ai-presence.mdx b/docs/pages/get-started/nextjs-ai-presence.mdx
new file mode 100644
index 0000000000..fb34d1b0a6
--- /dev/null
+++ b/docs/pages/get-started/nextjs-ai-presence.mdx
@@ -0,0 +1,343 @@
+---
+meta:
+ title: "Get started with AI Presence using Liveblocks and Next.js"
+ parentTitle: "Quickstart"
+ description:
+ "Learn how to show AI agents in your avatar stack and highlight what they’re
+ editing using Liveblocks Presence and Next.js"
+---
+
+Liveblocks is a realtime collaboration infrastructure for building performant
+collaborative experiences. Follow the following steps to show an AI agent as a
+real user inside your Next.js `/app` directory application: in the avatar stack,
+and as a highlighted box around the form field or cell it’s currently editing,
+using
+[`setPresence`](/docs/api-reference/liveblocks-node#post-rooms-roomId-presence)
+from [`@liveblocks/node`](/docs/api-reference/liveblocks-node) and the
+[`useOthers`](/docs/api-reference/liveblocks-react#useOthers) hook from
+[`@liveblocks/react`](/docs/api-reference/liveblocks-react).
+
+## Quickstart
+
+
+
+
+
+ Have a Presence app ready
+
+
+ To add AI Presence on top of your existing app, you first need a Liveblocks
+ Presence setup with [`AvatarStack`](/docs/api-reference/liveblocks-react-ui#AvatarStack)
+ and authenticated users. Open up your app, or set up presence if you
+ haven’t already.
+
+
+
+
+
+
+
+ Install `@liveblocks/node`
+
+
+ We’ll set the AI agent’s presence from the server, so install
+ [`@liveblocks/node`](/docs/api-reference/liveblocks-node).
+
+ ```bash trackEvent="install_liveblocks"
+ npm install @liveblocks/node
+ ```
+
+
+
+
+
+ Add your secret key
+
+
+ Create a `.env.local` file and add your Liveblocks secret key from the
+ [dashboard](/dashboard/apikeys).
+
+ ```env file=".env.local"
+ LIVEBLOCKS_SECRET_KEY="{{SECRET_KEY}}"
+ ```
+
+
+
+
+
+ Add an AI user to your database
+
+
+ The AI agent appears in the room like any other user, so it needs an ID,
+ name, and avatar. Add a dedicated user for your agent alongside your real
+ users, and return it from
+ [`resolveUsers`](/docs/api-reference/liveblocks-react#LiveblocksProviderResolveUsers)
+ so it can be rendered in
+ [`AvatarStack`](/docs/api-reference/liveblocks-react-ui#AvatarStack).
+
+ ```tsx title="Find where you fetch data in your resolver functions…"
+ {
+ // +++
+ const users = await fetchUsers(userIds);
+ // +++
+ // ...
+ }}
+ >
+ {children}
+
+ ```
+
+ ```ts title="…and modify the return values to include an AI user"
+ // +++
+ export const AI_USER_INFO = {
+ id: "__AI_AGENT",
+ info: {
+ name: "AI Assistant",
+ avatar: "https://liveblocks.io/api/avatar?u=__AI_AGENT&agent=true",
+ color: "#6366f1",
+ },
+ };
+ // +++
+
+ async function fetchUsers(userIds: string[]) {
+ const users = [];
+
+ for (const userId of userIds) {
+ // +++
+ if (userId === AI_USER_INFO.id) {
+ users.push(AI_USER_INFO);
+ continue;
+ }
+ // +++
+
+ const user = await __getUserFromDb__(userId);
+ users.push(user ? { id: userId, info: user.info } : undefined);
+ }
+
+ return users;
+ }
+ ```
+
+
+
+
+ Show the AI in your avatar stack
+
+
+ To make the AI appear in
+ [`AvatarStack`](/docs/api-reference/liveblocks-react-ui#AvatarStack) and [`useOthers`](/docs/api-reference/liveblocks-react#useOthers)
+ from the server, call [`setPresence`](/docs/api-reference/liveblocks-node#post-rooms-roomId-presence).
+ Use this to signify your agent is running a task in the room.
+
+ ```ts file="app/agent-presence.ts" highlight="11-16"
+ "use server";
+
+ import { Liveblocks } from "@liveblocks/node";
+ import { AI_USER_INFO } from "./database";
+
+ const liveblocks = new Liveblocks({
+ secret: process.env.LIVEBLOCKS_SECRET_KEY!,
+ });
+
+ export async function runAgentTask(roomId: string) {
+ // +++
+ await liveblocks.setPresence(roomId, {
+ userId: AI_USER_INFO.id,
+ userInfo: AI_USER_INFO.info,
+ data: {},
+ ttl: 30, // How many seconds it should appear
+ });
+ // +++
+
+ // Run your AI task or workflow
+ // ...
+ }
+ ```
+
+ The agent will now appear in presence alongside real users.
+
+
+
+
+
+ Show AI presence in custom UI
+
+
+ With [`useOthers`](/docs/api-reference/liveblocks-react#useOthers) you can create
+ custom AI presence within any UI. An example of this is showing a highlighted box
+ around the part of the interface that the AI is editing.
+
+ To set this up, first set presence types in your app. An `editingId` string can represent
+ an element that the AI is currently editing, such as a form field, and a value `null` can signify that
+ the AI is not editing anything.
+
+ ```ts file="liveblocks.config.ts"
+ declare global {
+ interface Liveblocks {
+ Presence: {
+ editingId: string | null;
+ };
+ }
+ }
+
+ export {};
+ ```
+
+ Next, when using [`setPresence`](/docs/api-reference/liveblocks-node#post-rooms-roomId-presence) on the server,
+ set the `editingId` property to the ID of the element that the AI is currently editing.
+
+ ```ts file="app/agent-presence.ts" highlight="11-16"
+ "use server";
+
+ import { Liveblocks } from "@liveblocks/node";
+ import { AI_USER_INFO } from "./database";
+
+ const liveblocks = new Liveblocks({
+ secret: process.env.LIVEBLOCKS_SECRET_KEY!,
+ });
+
+ export async function runAgentTask(roomId: string) {
+ await liveblocks.setPresence(roomId, {
+ userId: AI_USER_INFO.id,
+ userInfo: AI_USER_INFO.info,
+ // +++
+ data: {
+ editingId: "title-1",
+ },
+ // +++
+ ttl: 30,
+ });
+
+ // Edit the input field with AI
+ // ...
+ }
+ ```
+
+ On the client, use [`useOthers`](/docs/api-reference/liveblocks-react#useOthers)
+ to create a small component that draws a highlighted box around the targeted element
+ when the AI is editing it.
+
+
+ ```tsx file="app/AiPresenceEditFrame.tsx"
+ "use client";
+
+ import { useOthers, shallow } from "@liveblocks/react";
+ import { AI_USER_INFO } from "./database";
+ import { shallow } from "@liveblocks/react";
+
+ export function AiPresenceEditFrame({ editingId }: { editingId: string }) {
+ // Check if the AI user is online AND editing the current ID
+ const aiIsEditing = useOthers(((others) => {
+ const ai = others.find((o) => o.id === AI_USER_INFO.id);
+ return ai && ai.presence.editingId === editingId;
+ }), shallow);
+
+ if (!aiIsEditing) {
+ return children;
+ }
+
+ return (
+
+
+ {children}
+
+
+ );
+ }
+ ```
+
+ You can then wrap any part of your your UI with `AiPresenceEditFrame`, give each one a unique `editingId`,
+ and if the AI is editing that ID, a highlighted box will appear around it.
+
+ ```tsx file="app/Form.tsx"
+ "use client";
+
+ import { AiPresenceEditFrame } from "./AiPresenceEditFrame";
+
+ export function Form() {
+ return (
+
+ );
+ }
+ ```
+
+
+
+
+
+ Hide the AI when it’s done
+
+
+ You can optionally choose to hide the AI's presence when it's completed editing. To do
+ this, set the minimum `ttl` value to 2 seconds.
+
+ ```ts
+ await liveblocks.setPresence(roomId, {
+ userId: AI_USER_INFO.id,
+ userInfo: AI_USER_INFO.info,
+ data: { editingId: null },
+ // +++
+ ttl: 2,
+ // +++
+ });
+ ```
+
+ You have AI presence set up! In some apps, it may be useful to use multiple different IDs for AI, as this way
+ you can individually control when each AI appears and disappears.
+
+
+
+
+
+
+## What to read next
+
+Congratulations! You’ve set up the foundation for AI Presence in your Next.js
+application.
+
+- [@liveblocks/node API Reference](/docs/api-reference/liveblocks-node#post-rooms-roomId-presence)
+- [@liveblocks/react API Reference](/docs/api-reference/liveblocks-react#useOthers)
+- [Add AI agents to React Flow](/docs/get-started/nextjs-ai-react-flow)
+- [Notify users when an AI agent finishes](/docs/get-started/nextjs-ai-notifications)
+
+---
+
+## Examples using AI Presence
+
+
+
+
+
diff --git a/docs/pages/get-started/nextjs-ai-react-flow.mdx b/docs/pages/get-started/nextjs-ai-react-flow.mdx
new file mode 100644
index 0000000000..a49fdf1a03
--- /dev/null
+++ b/docs/pages/get-started/nextjs-ai-react-flow.mdx
@@ -0,0 +1,273 @@
+---
+meta:
+ title: "Get started with AI agents in React Flow using Liveblocks and Next.js"
+ parentTitle: "Quickstart"
+ description:
+ "Learn how to let an AI agent edit a collaborative React Flow diagram from
+ your Next.js server using Liveblocks."
+---
+
+Liveblocks is a realtime collaboration infrastructure for building performant
+collaborative experiences. Follow the following steps to add an AI agent that
+can read and edit a collaborative [React Flow](https://reactflow.dev) diagram
+from your Next.js `/app` directory application using
+[`mutateFlow`](/docs/api-reference/liveblocks-react-flow#mutateFlow) from
+[`@liveblocks/react-flow`](/docs/api-reference/liveblocks-react-flow), the
+[Vercel AI SDK](https://ai-sdk.dev), and [OpenAI](https://platform.openai.com).
+
+## Quickstart
+
+
+
+
+
+ Have a React Flow app ready
+
+
+ To let an AI edit your diagram, you first need a Liveblocks React Flow
+ app set up with secret key authentication. Open up your app, or set up
+ React Flow if you haven’t already.
+
+
+
+
+
+
+
+ Install dependencies
+
+
+ Install [`@liveblocks/node`](/docs/api-reference/liveblocks-node) and the
+ Node-side [`@liveblocks/react-flow`](/docs/api-reference/liveblocks-react-flow#mutateFlow)
+ entry point, along with the [Vercel AI SDK](https://ai-sdk.dev), the
+ [OpenAI provider](https://ai-sdk.dev/providers/ai-sdk-providers/openai),
+ and [`zod`](https://zod.dev) to validate tool inputs.
+
+ ```bash trackEvent="install_liveblocks"
+ npm install @liveblocks/node @liveblocks/react-flow ai @ai-sdk/openai zod
+ ```
+
+
+
+
+
+ Add your environment variables
+
+
+ Create a `.env.local` file and add your Liveblocks secret key from the
+ [dashboard](/dashboard/apikeys), and your OpenAI API key from the
+ [OpenAI dashboard](https://platform.openai.com/api-keys).
+
+ ```env file=".env.local"
+ LIVEBLOCKS_SECRET_KEY="{{SECRET_KEY}}"
+ OPENAI_API_KEY="sk-..."
+ ```
+
+
+
+
+
+ Create the AI agent
+
+
+ Create a server action that uses
+ [`mutateFlow`](/docs/api-reference/liveblocks-react-flow#mutateFlow) to
+ open the room’s flow on the server and let the AI add and update nodes
+ and edges. Each [Vercel AI SDK tool](https://ai-sdk.dev/docs/foundations/tools)
+ maps to one of the
+ [`MutableFlow`](/docs/api-reference/liveblocks-react-flow#mutable-flow)
+ methods like `flow.addNode`, `flow.updateNodeData`, or `flow.addEdge`.
+
+ ```ts file="app/run-flow-agent.ts"
+ "use server";
+
+ import { Liveblocks } from "@liveblocks/node";
+ import { mutateFlow } from "@liveblocks/react-flow/node";
+ import { generateText, stepCountIs, tool } from "ai";
+ import { openai } from "@ai-sdk/openai";
+ import { nanoid } from "nanoid";
+ import { z } from "zod";
+
+ const liveblocks = new Liveblocks({
+ secret: process.env.LIVEBLOCKS_SECRET_KEY!,
+ });
+
+ export async function runFlowAgent(formData: FormData) {
+ const roomId = String(formData.get("roomId") ?? "").trim();
+ const prompt = String(formData.get("prompt") ?? "").trim();
+ if (!roomId || !prompt) return;
+
+ await mutateFlow({ client: liveblocks, roomId }, async (flow) => {
+ await generateText({
+ model: openai("gpt-4.1-mini"),
+ system: `You edit a live collaborative React Flow diagram.
+ - Each node has: { id, position: { x, y }, data: { label } }.
+ - Each edge has: { id, source, target }.
+ - Make small, deliberate changes that are easy to follow.
+ - Use 150px horizontal and 100px vertical spacing between nodes.`,
+ prompt: `${JSON.stringify(flow.toJSON(), null, 2)}
+ ${prompt}`,
+ tools: {
+ addNode: tool({
+ description: "Add a node to the diagram.",
+ inputSchema: z.object({
+ label: z.string(),
+ position: z.object({ x: z.number(), y: z.number() }),
+ }),
+ execute: ({ label, position }) => {
+ const id = `node-${nanoid(6)}`;
+ flow.addNode({ id, position, data: { label } });
+ return { ok: true, id };
+ },
+ }),
+ updateNodeData: tool({
+ description: "Update one node’s label.",
+ inputSchema: z.object({
+ id: z.string(),
+ label: z.string(),
+ }),
+ execute: ({ id, label }) => {
+ if (!flow.getNode(id)) return { ok: false, missing: true };
+ flow.updateNodeData(id, { label });
+ return { ok: true, id };
+ },
+ }),
+ addEdge: tool({
+ description: "Connect two existing nodes with an edge.",
+ inputSchema: z.object({
+ source: z.string(),
+ target: z.string(),
+ }),
+ execute: ({ source, target }) => {
+ if (!flow.getNode(source) || !flow.getNode(target)) {
+ return { ok: false, missing: true };
+ }
+ const id = `e-${source}-${target}-${nanoid(4)}`;
+ flow.addEdge({ id, source, target });
+ return { ok: true, id };
+ },
+ }),
+ },
+ stopWhen: stepCountIs(20),
+ });
+ });
+ }
+ ```
+
+ `mutateFlow` opens the room’s flow for reading _and_ mutating. Any changes
+ made through the `flow` object are intelligently synced to all connected
+ clients via Liveblocks Storage, so the diagram updates in realtime as the
+ AI works.
+
+
+
+
+
+ Add a prompt form to the page
+
+
+ Now add a small form that lets users describe what the agent should do.
+ It uses [`useRoom`](/docs/api-reference/liveblocks-react#useRoom) to get
+ the current room ID and passes it to the server action.
+
+ ```tsx file="app/FlowAgentForm.tsx"
+ "use client";
+
+ import { useRoom } from "@liveblocks/react/suspense";
+ import { useState } from "react";
+ import { runFlowAgent } from "./run-flow-agent";
+
+ export function FlowAgentForm() {
+ const roomId = useRoom().id;
+ const [prompt, setPrompt] = useState("");
+
+ return (
+
+ );
+ }
+ ```
+
+ Then render it next to your existing `Flow` component:
+
+ ```tsx file="app/page.tsx"
+ import { Room } from "./Room";
+ import { Flow } from "./Flow";
+ // +++
+ import { FlowAgentForm } from "./FlowAgentForm";
+ // +++
+
+ export default function Page() {
+ return (
+
+ // +++
+
+ // +++
+
+
+ );
+ }
+ ```
+
+
+
+
+
+ Next: show the agent in the room
+
+
+ Your AI agent now reads and writes to your React Flow diagram in realtime.
+ Next, give the agent a face—show its avatar in the avatar stack and
+ highlight the nodes it’s editing using Liveblocks Presence.
+
+
+
+
+
+
+
+
+## What to read next
+
+Congratulations! You’ve set up the foundation for an AI agent that can edit your
+collaborative React Flow diagrams.
+
+- [`mutateFlow` API reference](/docs/api-reference/liveblocks-react-flow#mutateFlow)
+- [`MutableFlow` API](/docs/api-reference/liveblocks-react-flow#mutable-flow)
+- [@liveblocks/react-flow API reference](/docs/api-reference/liveblocks-react-flow)
+- [Vercel AI SDK tools](https://ai-sdk.dev/docs/foundations/tools)
+
+---
+
+## Examples using React Flow and AI
+
+
+
+
diff --git a/docs/pages/get-started/nextjs-notifications-custom-in-app.mdx b/docs/pages/get-started/nextjs-notifications-custom-in-app.mdx
index 81b1b8a1e1..985cf3021f 100644
--- a/docs/pages/get-started/nextjs-notifications-custom-in-app.mdx
+++ b/docs/pages/get-started/nextjs-notifications-custom-in-app.mdx
@@ -45,6 +45,57 @@ from [`@liveblocks/react-ui`](/docs/api-reference/liveblocks-react-ui).
+
+
+ Add your secret key
+
+
+ Create a `.env.local` file and add your Liveblocks secret key from the
+ [dashboard](/dashboard/apikeys).
+
+ ```env file=".env.local"
+ LIVEBLOCKS_SECRET_KEY="{{SECRET_KEY}}"
+ ```
+
+
+
+
+
+ Set up authentication
+
+
+ Create an [authentication](/docs/authentication) API route with
+ [`identifyUser`](/docs/api-reference/liveblocks-node#id-tokens),
+ passing a unique user ID.
+
+ ```ts file="app/api/liveblocks-auth/route.ts"
+ import { Liveblocks } from "@liveblocks/node";
+
+ const liveblocks = new Liveblocks({
+ secret: process.env.LIVEBLOCKS_SECRET_KEY!,
+ });
+
+ export async function POST(request: Request) {
+ // Get the current user from your database
+ const user = __getUserFromDB__(request);
+
+ // Identify the user and return the result
+ const { status, body } = await liveblocks.identifyUser(
+ { userId: user.id },
+ {
+ userInfo: {
+ name: user.name,
+ avatar: user.avatar,
+ },
+ }
+ );
+
+ return new Response(body, { status });
+ }
+ ```
+
+
+
Create a Liveblocks provider
@@ -64,7 +115,7 @@ from [`@liveblocks/react-ui`](/docs/api-reference/liveblocks-react-ui).
export function Providers({ children }: { children: ReactNode }) {
return (
-
+
{children}
);
@@ -168,7 +219,7 @@ from [`@liveblocks/react-ui`](/docs/api-reference/liveblocks-react-ui).
import { Liveblocks } from "@liveblocks/node";
const liveblocks = new Liveblocks({
- secret: "{{SECRET_KEY}}",
+ secret: process.env.LIVEBLOCKS_SECRET_KEY!,
});
// Call this in your app to create a custom notification
@@ -245,11 +296,11 @@ from [`@liveblocks/react-ui`](/docs/api-reference/liveblocks-react-ui).
- Next: authenticate and add your users
+ Next: add your users
- Notifications is set up and working now, but each user is anonymous—the next step is to
- authenticate each user as they connect, and attach their name and avatar to their notifications.
+ Notifications is set up and working now, but the auth route is using a placeholder
+ user—the next step is to connect it to your real users, and attach their name and avatar to their notifications.
@@ -43,6 +43,57 @@ from [`@liveblocks/react-ui`](/docs/api-reference/liveblocks-react-ui).
+
+
+ Add your secret key
+
+
+ Create a `.env.local` file and add your Liveblocks secret key from the
+ [dashboard](/dashboard/apikeys).
+
+ ```env file=".env.local"
+ LIVEBLOCKS_SECRET_KEY="{{SECRET_KEY}}"
+ ```
+
+
+
+
+
+ Set up authentication
+
+
+ Create an [authentication](/docs/authentication) API route with
+ [`identifyUser`](/docs/api-reference/liveblocks-node#id-tokens),
+ passing a unique user ID.
+
+ ```ts file="app/api/liveblocks-auth/route.ts"
+ import { Liveblocks } from "@liveblocks/node";
+
+ const liveblocks = new Liveblocks({
+ secret: process.env.LIVEBLOCKS_SECRET_KEY!,
+ });
+
+ export async function POST(request: Request) {
+ // Get the current user from your database
+ const user = __getUserFromDB__(request);
+
+ // Identify the user and return the result
+ const { status, body } = await liveblocks.identifyUser(
+ { userId: user.id },
+ {
+ userInfo: {
+ name: user.name,
+ avatar: user.avatar,
+ },
+ }
+ );
+
+ return new Response(body, { status });
+ }
+ ```
+
+
+
Create a Liveblocks provider
@@ -62,7 +113,7 @@ from [`@liveblocks/react-ui`](/docs/api-reference/liveblocks-react-ui).
export function Providers({ children }: { children: ReactNode }) {
return (
-
+
{children}
);
@@ -152,11 +203,11 @@ from [`@liveblocks/react-ui`](/docs/api-reference/liveblocks-react-ui).
- Next: authenticate and add your users
+ Next: add your users
- Notifications is set up and working now, but each user is anonymous—the next step is to
- authenticate each user as they connect, and attach their name and avatar to their notifications.
+ Notifications is set up and working now, but the auth route is using a placeholder
+ user—the next step is to connect it to your real users, and attach their name and avatar to their notifications.
- Use the Liveblocks hooks
+ Use the Liveblocks components
Next, create `CollaborativeApp.tsx` and add our
@@ -111,7 +111,7 @@ the [`@liveblocks/react`](/docs/api-reference/liveblocks-react) package.
hooks such as [`useOthers`](/docs/api-reference/liveblocks-react#useOthers) and
[`useMyPresence`](/docs/api-reference/liveblocks-react#useMyPresence).
- ```tsx file="app/CollaborativeApp.tsx" highlight="6"
+ ```tsx file="app/CollaborativeApp.tsx" highlight="8-9"
"use client";
import { AvatarStack, Cursors } from "@liveblocks/react-ui";
diff --git a/docs/routes.json b/docs/routes.json
index dc2debbe4b..631294ac05 100644
--- a/docs/routes.json
+++ b/docs/routes.json
@@ -36,6 +36,21 @@
"path": "/get-started/nextjs-ai-chat",
"hidden": true
},
+ {
+ "title": "AI Presence",
+ "path": "/get-started/nextjs-ai-presence",
+ "hidden": true
+ },
+ {
+ "title": "AI / React Flow",
+ "path": "/get-started/nextjs-ai-react-flow",
+ "hidden": true
+ },
+ {
+ "title": "AI / Notifications",
+ "path": "/get-started/nextjs-ai-notifications",
+ "hidden": true
+ },
{
"title": "Feeds",
"path": "/get-started/nextjs-feeds",