by jax

Liveblocks provides building blocks and infrastructure for adding realtime collaboration, comments, AI agents, and notifications to any web application. Designed for developers integrating React, Next.js, and popular editors.
This block provides the full Liveblocks monorepo: a real-time collaboration infrastructure including presence, storage, comments, notifications, and AI agent support. It targets teams building collaborative web applications in React/Next.js who need production-ready multiplayer primitives without managing WebSocket infrastructure.
.claude/ - Claude AI assistant settings for the monorepo.github/ - CI/CD workflows, issue templates, and PR templates.vscode/ - Editor settings for the monorepo workspaceassets/ - Static assets including documentation imagesdocs/ - Documentation source filesexamples/ - Runnable Next.js example apps demonstrating each Liveblocks featureguides/ - Step-by-step integration guidespackages/ - All publishable npm packages (@liveblocks/client, @liveblocks/react, etc.)scripts/ - Build, release, and tooling scriptsshared/ - Shared internal utilities across packagesstarter-kits/ - Boilerplate projects for common use casestools/ - Internal developer toolingtutorial/ - Interactive tutorial sourcepackage.json - Monorepo root manifest (pnpm workspaces)pnpm-workspace.yaml - Workspace package glob configurationturbo.json - Turborepo pipeline configurationCONTRIBUTING.MD - Contributor setup and workflow guideCHANGELOG.md - Full version historyLICENSE - Apache-2.0 / AGPL-3.0 dual license termsnpm install @liveblocks/client @liveblocks/react
npm install @liveblocks/react-ui # pre-built UI components (Comments, etc.)
npm install @liveblocks/node # server-side auth and REST helpers
npm install @liveblocks/yjs # Yjs CRDT provider (if using Yjs editors)
npm install @liveblocks/react-tiptap # Tiptap rich text integration
npm install @liveblocks/react-lexical # Lexical rich text integration
npm install @liveblocks/redux # Redux middleware (if using Redux)
npm install @liveblocks/zustand # Zustand middleware (if using Zustand)
npm install @liveblocks/emails # Email notification rendering
Spin up an isolated sandbox and run it server-side — no local setup.
Tetrees AI Review of this version
This TypeScript cli / script completed archive review. Structure, dependency manifests, documentation, functional source, and common risk patterns were checked by the Tetrees verification pipeline; runtime phases are stated separately.
Deterministic AVCP artifact review
Pipeline avcp-2026-08-04.1 · SHA-256 e429482b1cdb064f…
This version-scoped review deterministically inspects the submitted archive for structure, dependencies, documentation, functional source, and common malicious or high-risk signals. Build and test phases are reported as passed only after an isolated sandbox audition. It is not a guarantee of perfect security.
Reviewed Aug 4, 2026
Push this product straight into your AI IDE, web builder or cloud IDE.
Connect Tetrees to a compatible AI IDE, list products you own, and request the verified ZIP without exposing seller upload controls.
No reviews yet.
Sign in to join the discussion
Loading discussion…
No native build steps required. Liveblocks is pure JavaScript/TypeScript and works in any Node.js environment. For Next.js App Router, ensure "use client" directives are added to any file using Liveblocks React hooks.
Copy the packages you need. From source/packages/, the relevant directories are @liveblocks/client, @liveblocks/react, and @liveblocks/node. Install from npm rather than source unless you are patching internals.
Create a Liveblocks account at liveblocks.io and obtain a secret key and a public key from your dashboard.
Set environment variables:
LIVEBLOCKS_SECRET_KEY=sk_prod_xxxxxxxxxxxx
NEXT_PUBLIC_LIVEBLOCKS_PUBLIC_KEY=pk_prod_xxxxxxxxxxxx
pages/api/liveblocks-auth.ts):import { Liveblocks } from "@liveblocks/node";
import type { NextApiRequest, NextApiResponse } from "next";
const liveblocks = new Liveblocks({ secret: process.env.LIVEBLOCKS_SECRET_KEY! });
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const { status, body } = await liveblocks.identifyUser(
{ userId: "user-123", userInfo: { name: "Alice" } },
{ userInfo: {} }
);
res.status(status).end(body);
}
RoomProvider (see examples in source/examples/):import { RoomProvider } from "@liveblocks/react";
export default function App() {
return (
<RoomProvider id="my-room" initialPresence={{ cursor: null }}>
<YourApp />
</RoomProvider>
);
}
.d.ts files. Set "moduleResolution": "bundler" or "node16" in tsconfig.json for proper ESM resolution.function useStorage<T>(selector: (root: LiveObject<YourStorage>) => T): T | null
Subscribes a React component to a slice of the room's persistent storage. Returns null while the storage is loading. Use this to read shared state that persists after all users leave (form contents, canvas shapes, color configs). Re-renders only when the selected value changes.
function useMutation<F extends (context: MutationContext, ...args: any[]) => any>(
callback: F,
deps: readonly unknown[]
): (...args: Rest<Parameters<F>>) => ReturnType<F>
Returns a stable callback that executes a mutation against Liveblocks Storage. The context object provides { storage, self, others, setMyPresence }. Use this for all writes to shared storage—never mutate storage directly inside render. The deps array mirrors useCallback.
function useMyPresence<P extends JsonObject>(): [P, (patch: Partial<P>) => void]
function useUpdateMyPresence<P extends JsonObject>(): (patch: Partial<P>, options?: { addToHistory: boolean }) => void
Read and update the current user's ephemeral presence (cursor position, selected element, active field). Presence is not persisted—it disappears when the user disconnects. useUpdateMyPresence is a convenience hook when you only need to write.
function useOthersMapped<T>(
selector: (other: User<Presence, UserMeta>) => T,
isEqual?: (a: T, b: T) => boolean
): ReadonlyArray<readonly [connectionId: number, T]>
Returns a mapped array of other connected users' data. Each entry is a [connectionId, selectedValue] tuple. Use this to render avatars, cursors, or selections for all other users without subscribing to full presence objects, minimizing re-renders.
function RoomProvider(props: {
id: string;
initialPresence: Presence | (() => Presence);
initialStorage?: () => { [key: string]: LiveObject | LiveList | LiveMap };
children: React.ReactNode;
}): JSX.Element
Connects to a Liveblocks room and provides context to all child hooks. The id must be unique per collaboration session. initialStorage runs only once when the room storage is first created.
Multiple users edit a shared form; changes persist after everyone disconnects.
import { RoomProvider, useStorage, useMutation, useUpdateMyPresence } from "@liveblocks/react";
import { LiveObject } from "@liveblocks/client";
function FormField({ fieldId }: { fieldId: string }) {
const updateMyPresence = useUpdateMyPresence();
const value = useStorage((root) => (root.fields as any)?.[fieldId] ?? "");
const updateField = useMutation(({ storage }, newValue: string) => {
storage.get("fields").set(fieldId, newValue);
}, [fieldId]);
return (
<input
value={value ?? ""}
onFocus={() => updateMyPresence({ focusedField: fieldId })}
onBlur={() => updateMyPresence({ focusedField: null })}
onChange={(e) => updateField(e.target.value)}
/>
);
}
export default function CollaborativeForm() {
return (
<RoomProvider
id="collab-form-room"
initialPresence={{ focusedField: null }}
initialStorage={() => ({ fields: new LiveObject({ title: "", body: "" }) })}
>
<FormField fieldId="title" />
<FormField fieldId="body" />
</RoomProvider>
);
}
Show all connected users' cursor positions in real time.
import { useMyPresence, useOthersMapped } from "@liveblocks/react";
function CursorOverlay() {
const others = useOthersMapped((other) => other.presence.cursor);
return (
<div style={{ position: "fixed", inset: 0, pointerEvents: "none" }}>
{others.map(([connectionId, cursor]) =>
cursor ? (
<div
key={connectionId}
style={{ position: "absolute", left: cursor.x, top: cursor.y, width: 12, height: 12, background: "red", borderRadius: "50%" }}
/>
) : null
)}
</div>
);
}
function App() {
const [, updateMyPresence] = useMyPresence();
return (
<div
onPointerMove={(e) => updateMyPresence({ cursor: { x: e.clientX, y: e.clientY } })}
onPointerLeave={() => updateMyPresence({ cursor: null })}
style={{ width: "100vw", height: "100vh" }}
>
<CursorOverlay />
<p>Move your cursor</p>
</div>
);
}
Persist per-material colors across sessions, mirroring examples/nextjs-3d-builder.
import { useStorage, useMutation } from "@liveblocks/react";
import { LiveObject } from "@liveblocks/client";
import { useState } from "react";
function ColorEditor() {
const [selectedMaterial, setSelectedMaterial] = useState<string | null>(null);
const colors = useStorage((root) => root.colors as Record<string, string> | null);
const setColor = useMutation(({ storage }, color: string) => {
if (selectedMaterial) {
storage.get("colors").set(selectedMaterial, color);
}
}, [selectedMaterial]);
if (!colors) return <div>Loading...</div>;
return (
<div>
{["sole", "laces", "upper"].map((part) => (
<button key={part} onClick={() => setSelectedMaterial(part)}>
{part}: {colors[part] ?? "#ffffff"}
</button>
))}
{selectedMaterial && (
<input type="color" onChange={(e) => setColor(e.target.value)} />
)}
</div>
);
}
// RoomProvider initialStorage:
// initialStorage={() => ({ colors: new LiveObject({ sole: "#ffffff", laces: "#000000", upper: "#ff0000" }) })}
.claude/ - Settings for Claude AI tooling used during development of the monorepo itself..github/ - GitHub Actions CI pipelines, Dependabot config, PR templates, and visual assets..vscode/ - Workspace-level VS Code settings and recommended extensions.assets/ - Marketing and documentation images referenced by README and docs.docs/ - MDX documentation source that powers liveblocks.io/docs.examples/ - Standalone Next.js apps; each demonstrates one Liveblocks feature and is directly runnable.guides/ - Longer form integration guides, typically paired with blog posts.packages/ - All published npm packages; each subdirectory is an independent package with its own package.json.scripts/ - Release automation, changelog generation, and workspace maintenance scripts.shared/ - Private internal utilities shared across packages (not published to npm).starter-kits/ - Minimal project templates for bootstrapping new Liveblocks apps.tools/ - Internal CLI tools and code generators used during development.tutorial/ - Source for the interactive Liveblocks tutorial on the website.package.json - Root manifest declaring pnpm workspaces and shared dev dependencies.pnpm-workspace.yaml - Defines which directories are workspace packages.turbo.json - Turborepo task pipeline (build, test, lint dependency graph).CONTRIBUTING.MD - How to set up the local monorepo, run tests, and submit PRs.CHANGELOG.md - Complete internal version history across all packages.LICENSE - Apache-2.0 for client packages, AGPL-3.0 for server packages.RoomProvider: All useStorage, useMutation, useMyPresence, and useOthersMapped calls must be descendants of a <RoomProvider>. Fix: ensure RoomProvider wraps the component tree before any hook call.useStorage returns null on first render: Storage is async. Always guard with if (!data) return <Loading /> before accessing nested properties.useMutation deps array stale closure: Treat deps identically to useCallback. Omitting a dependency (e.g. selectedMaterial) causes stale closures. Fix: include all variables referenced inside the mutation callback."use client" as the first line. Fix: add the directive or move hooks to a client boundary component.LIVEBLOCKS_SECRET_KEY must only be used in server-side auth endpoints. Never pass it to client bundles. Fix: prefix public keys with NEXT_PUBLIC_ only for pk_ keys.@liveblocks/node ships ESM. If your server uses CommonJS (require()), set "type": "module" in package.json or use dynamic import(). Fix: use import { Liveblocks } from "@liveblocks/node" in ESM context.I have the Liveblocks monorepo source in the `source/` directory and a usage guide in `USAGE.md`.
The upstream package is `@liveblocks/monorepo` (liveblocks.io collaboration infrastructure).
My project is: [DESCRIBE YOUR PROJECT - e.g. "a Next.js 14 app with App Router where users collaboratively edit documents"].
Please integrate Liveblocks into my project step by step:
1. Read `USAGE.md` and `source/examples/` for real import paths and hook signatures.
2. Install the required npm packages listed in `USAGE.md` into my project.
3. Create a server-side auth endpoint using `@liveblocks/node` that authenticates my existing users.
My auth system is: [DESCRIBE - e.g. "NextAuth.js with JWT sessions"].
4. Wrap my root layout (or `_app.tsx`) with `RoomProvider` using the room ID pattern from the examples.
5. Add the following collaborative features:
- [FEATURE 1 - e.g. "live cursors showing all connected users"]
- [FEATURE 2 - e.g. "persistent shared state for document title and content"]
- [FEATURE 3 - e.g. "user avatars with presence"]
6. Use only hooks and components visible in `USAGE.md`'s Public API section. Do not invent new APIs.
7. Add TypeScript types for my Presence and Storage shapes.
8. Show me the final file structure and any environment variables I need to set.
My current project structure: [PASTE YOUR DIRECTORY TREE]
Liveblocks packages are dual-licensed: client-side packages (@liveblocks/client, @liveblocks/react, etc.) are released under Apache-2.0; server-side packages (@liveblocks/node, etc.) are released under AGPL-3.0. See source/LICENSE for the full license text.
Upstream source: github.com/liveblocks/liveblocks | liveblocks.io
This product’s unique contribution is clean room implementation of valuable code block into AVCP compatible standard.
The full install guide and integration prompts unlock after purchase.
PHP, Laravel & Business Scripts
Free