This September & October, we’ve added a number of features across the board:

- [Multi-tenancy](#multi-tenancy): Build collaborative apps that serve multiple
  organizations.
- [Tiptap 3.0 support](#tiptap-3.0-support): Upgrade to the latest versions of
  Tiptap & BlockNote.
- [Group mentions](#group-mentions): Tag groups of users in comments, like
  `@everyone`.
- [Numerical thread filters](#numerical-thread-filters): Use greater/less than
  metadata filters in threads.
- [Batched notifications](#batched-notifications): Update existing notifications
  with new content.
- [Filter notification counts](#filter-notification-counts): Display filtered
  unread notification badges.
- [AI chat web search](#ai-chat-web-search): Give your AI the ability to search
  the web.
- [AI chat status hook](#ai-chat-status-hook): Create AI chat status indicators
  & loading spinners.
- [New AI Copilots examples & docs](#new-ai-copilots-examples-and-docs): Learn
  how to build advanced AI Copilots.
- [Liveblocks AI assistant](#liveblocks-ai-assistant): Get AI help from our
  documentation & dashboard.
- [Dashboard improvements](#dashboard-improvements): Better user experience &
  clarity in our dashboard.

## Upgrade now

To use the latest features, update your packages with the following command.

```bash
npx create-liveblocks-app@latest --upgrade
```

If you were previously on Liveblocks 3.9 or below, make sure to follow our
[upgrade guides](/docs/platform/upgrading) before updating.

## Multi-tenancy [#multi-tenancy]

Liveblocks now fully supports multi-tenancy with the new
[Organizations](/docs/authentication/organizations) feature, making it easier
than ever to build collaborative apps that serve multiple organizations, all
within a single project.

### What does this mean?

A common pattern in SaaS apps is to have an organization switcher in the corner
of the app, allowing users to switch between different organizations, or
organizations.

<Figure>
  <Image
    src="/images/blog/whats-new-in-liveblocks-october-25/org-switcher.png"
    alt="Organization switcher"
    width={672}
    height={420}
    quality={95}
  />
</Figure>

Liveblocks now supports this out of the box, with rooms and notifications being
scoped to a specific organization. For example, if a user is part of multiple
organizations, each organization will have its own inbox, and the user will only
receive notifications created by users in the current organization.

### Setting up Organizations

To set up Organizations, assign a specific organization ID as you create a room
on the server.

```ts
const room = await liveblocks.createRoom("my-room-id", {
  // +++
  organizationId: "my-organization-id",
  // +++
});
```

When authenticating a user, assign the same organization ID, and they will only
be able to access rooms and activity assigned to that organization.

```ts
// If you're using access token auth...
const session = liveblocks.prepareSession("olivier@example.com", {
  // +++
  organizationId: "organization123",
  // +++
});

// If you're using ID token auth...
const { body, status } = await liveblocks.identifyUser({
  userId: "olivier@example.com",
  // +++
  organizationId: "organization123",
  // +++
});
```

Rooms, comments, storage, mentions, notifications, and virtually all Liveblocks
features can be scoped. Learn more in our documentation under
[organizations](/docs/authentication/organizations).

## Tiptap 3.0 support [#tiptap-3.0-support]

You can now use Tiptap 3.0 on Liveblocks, allowing you to take advantage of
features such as better static rendering, JSX rendering, improved TypeScript
support, and more. With this change, Liveblocks now supports the latest versions
of BlockNote too.

<Figure>
  <MuxVideo
    playbackId="FKgtiHXc4yZ9llomuePsTh02Dr02301R86RVCIgrmZYnQg"
    alt="Tiptap 3.0 demo"
  />
</Figure>

Each of our [Tiptap examples](/examples/browse/text-editor) has been updated to
use Tiptap 3.0, as well as our [Next.js Starter Kit](/nextjs-starter-kit), which
allows you to install and test a full collaborative application.

```bash
npx create-liveblocks-app@latest --next
```

### Migrating from Tiptap 2

To update your existing application to Tiptap 3.0, follow the instructions in
our [Liveblocks 3.10 upgrade guide](/docs/platform/upgrading/3.10). Future
versions of Liveblocks will require Tiptap 3.0.

## Group mentions [#group-mentions]

We’ve added support for group mentions in threads, inbox notifications, and text
editors, meaning you can now tag entire groups of users at once, for example
`@everyone` or `@engineering`.

<Figure>
  <MuxVideo
    playbackId="UgbGgcHTg3g9oTV3T02McYw4nnU35PaaHDLsvv2hcIrM"
    alt="Group mentions in comments"
  />
</Figure>

You can set up group mentions in two different ways, either by providing a list
of user IDs on the client, most helpful for tags such as `@everyone`, or by
creating managed, permanent groups on the server, helpful for creating specific
teams of users, such as `@engineering`.

```ts
// Creating a managed `@engineering` group
const group = await liveblocks.createGroup({
  groupId: "engineering",
  memberIds: ["marc@example.com", "florent@example.com"],
});
```

Related to the second method, there are a number of new methods allowing you to
modify and manage your groups. Learn more about both methods of creating groups
under
[group mentions](/docs/ready-made-features/comments/users-and-mentions#Group-mentions)
in our documentation.

## Numerical thread filters [#numerical-thread-filters]

When you create a new [Comments](/comments) thread, you can attach custom
metadata properties to it. You can now filter for comments with numeric metadata
values greater or less than a specific value. In this example, you can see how
`gt` represents “greater than”.

```ts title="Threads with ‘priority’ greater than 3"
const { threads } = useThreads({
  query: {
      // priority > 3
      // +++
      priority: {
        gt: 3,
      },
      // +++
    },
  },
});
```

You can combine operators to create ranges, which is particularly powerful in
combination with tables. For example, if your app is a spreadsheet, you can
filter for threads that are on screen for the user, around their current row and
column.

```ts title="Threads with a ‘row’ between 0 and 100, and a ‘column’ between 50 and 150"
const { threads } = useThreads({
  query: {
      // 0 <= row <= 100
      // 50 <= column <= 150
      // +++
      row: {
        gte: 0,
        lte: 100,
      },
      column: {
        gte: 50,
        lte: 150,
      }
      // +++
    },
  },
});
```

This filter supports 4 operators in total: `gt` - “greater than”, `lt` - “less
than”, `gte` - “greater than or equal to”, `lte` - “less than or equal to”.
Learn more in our documentation under
[`useThreads`](/docs/api-reference/liveblocks-react#useThreads).

## Batched notifications [#batched-notifications]

Notifications can now be batched, meaning you update existing notifications,
replacing their content, or adding new content to them. This is particularly
useful for changing statuses in notifications, or adding timelines of events,
such as in the video below.

<Figure
  caption={
    <>
      Updating a timeline within a notification—
      <Link href="/examples/notifications-custom">
        Custom Notifications
      </Link>{" "}
      example.
    </>
  }
>
  <MuxVideo
    playbackId="CKzoeOZ023KZaowoO02ekpnh28VTGPoxAn00QdayXNdnwk"
    alt="batched-notifications-blog.mp4"
  />
</Figure>

To set up batching, you need to set your custom notification kind as a batched
kind in the [dashboard](/dashboard).

<MuxVideo
  playbackId="s01MuDUm02tccH26UqjWOSAe4up522F1m02wBeXrUZz9ww"
  alt="Setting up notification batching in the dashboard"
/>

Learn more in our documentation under
[notification batching](/docs/ready-made-features/notifications/concepts#Notification-batching).

## Filter notification counts [#filter-notification-counts]

When using [Notifications](/notifications), you can easily display an unread
notification count for the current user, typically displayed in a small badge.
Previously, this count would sum _every_ unread notification the user had, but
you can now filter the count by room ID.

```tsx title="Only count unread notifications for a specific room"
const { count } = useUnreadInboxNotificationsCount({
  query: {
    // Count unread notifications created in "my-room-id"
    // +++
    roomId: "my-room-id",
    // +++
  },
});
```

You can also filter the count by
[notification kind](/docs/ready-made-features/notifications/concepts#Notification-kinds),
if you’d only like to count a specific type of notification, such as thread
notifications.

```tsx title="Only count unread ‘thread’ notifications"
const { count } = useUnreadInboxNotificationsCount({
  query: {
    // Count unread "thread" notifications
    // +++
    kind: "thread",
    // +++
  },
});
```

[Custom notification kinds](/docs/ready-made-features/notifications/concepts#Custom-notifications)
work with this filter too. Learn more in our documentation under
[`useUnreadInboxNotificationsCount`](/docs/api-reference/liveblocks-react#useUnreadInboxNotificationsCount).

## AI chat web search [#ai-chat-web-search]

[AI Copilots](/ai-copilots) now has web search, allowing you to ask your AI to
search the web for information. After querying, the search term and a list of
sources are displayed.

<Figure>
  <MuxVideo
    playbackId="LPc01s7mPfwiVZvZq49BoGfmOv1pGCrb8bcZ5tPKezEM"
    alt="AI web search"
  />
</Figure>

To enable this feature, toggle the “Web search” setting for your AI copilot in
the [dashboard](/dashboard), or set it from our back-end APIs,
[learn more](/docs/ready-made-features/ai-copilots/knowledge#Web-search). Most
OpenAI and Anthropic models support web search.

## AI chat status hook [#ai-chat-status-hook]

You can now create status indicators and loading spinners in your UI based on
the status of an AI chat. The new
[`useAiChatStatus`](/docs/api-reference/liveblocks-react#useAiChatStatus) hook
for [AI Copilots](/ai-copilots) allows you to render different components based
on whether an AI chat is idle, generating, or loading.

```tsx
function Status() {
  const { status } = useAiChatStatus("my-chat-id");

  if (status === "idle") {
    return <>🟢 Ready</>;
  }

  if (status === "generating") {
    return <>🔄 Generating…</>;
  }

  return <>🟡 Loading…</>;
}
```

You can also use the hook to check which
[AI tool](/docs/ready-made-features/ai-copilots/tools) is currently running.
Learn more in our documentation under
[`useAiChatStatus`](/docs/api-reference/liveblocks-react#useAiChatStatus).

## New AI Copilots examples & docs [#new-ai-copilots-examples-and-docs]

We’ve added two new [AI Copilots](/ai-copilots) examples to our collection,
exhibiting different ways to use advanced Liveblocks AI features in your app,
along with greatly expanded documentation, detailing how to build them.

### AI App Builder example

The first example is our [AI app builder](/examples/ai-app-builder), which uses
[AI tool calls](/docs/ready-made-features/ai-copilots/tools) to generate
websites, in particular React code. After the code’s generated, a live preview
updates with the AI-generated website.

<Figure>
  <MuxVideo
    playbackId="1vRUr9kcco3CrjKcXihPGcD01986tAofZ5OkObvcppJY"
    alt="AI app builder"
  />
</Figure>

The code is streamed as it’s generated into a Monaco code editor, displaying
[AI presence](/docs/ready-made-features/ai-copilots/tools#Streaming-into-a-document-with-AI-presence)
as it arrives.

<Figure>
  <MuxVideo
    playbackId="AuY98avoSWqXcRCy2m41FrQcExbhuJ001ze2Z5VhJvLA"
    alt="Tool call streaming"
  />
</Figure>

The code, and a live demo, can be found in our examples gallery:
[AI app builder](/examples/ai-app-builder).

### AI Calendar example

The second example is our [AI calendar](/examples/ai-calendar), which uses
[AI actions](/docs/ready-made-features/ai-copilots/tools#Actions) to generate an
event, and then add it. Every event is fed into the AI as
[front-end knowledge](/docs/ready-made-features/ai-copilots/knowledge#Front-end-knowledge),
allowing the AI to understand the current state of the calendar, and make
context-aware decisions.

<Figure>
  <MuxVideo
    playbackId="o8MpD4HQvB8hiWFpVKgLNgu6GEzei029NVaZoownQqhI"
    alt="AI Calendar"
  />
</Figure>

The code, and a live demo, can be found in our examples gallery:
[AI calendar](/examples/ai-calendar).

### New documentation

We’ve added a wealth of new information to our AI Copilots documentation,
including pages and code snippets detailing every way to use our product.

- Learn how to
  [set up your copilots](/docs/ready-made-features/ai-copilots/copilots#Creating-a-copilot),
  get advice on
  [creating system prompts](/docs/ready-made-features/ai-copilots/copilots#System-prompt),
  and
  [using advanced settings](/docs/ready-made-features/ai-copilots/copilots#Configuring-advanced-settings).
- Discover each way to use our
  [hooks](/docs/ready-made-features/ai-copilots/hooks), for example to
  [list a user’s chats](/docs/ready-made-features/ai-copilots/hooks#List-a-user's-chats),
  [modify AI chats](/docs/ready-made-features/ai-copilots/hooks#Create-and-delete-chats),
  and
  [send messages from outside the chat](/docs/ready-made-features/ai-copilots/hooks#Send-messages-to-a-chat).
- Try [adding knowledge](/docs/ready-made-features/ai-copilots/knowledge), our
  way to pass information to your AI through your
  [front-end](/docs/ready-made-features/ai-copilots/knowledge#Front-end-knowledge)
  with JSON and your
  [back-end](/docs/ready-made-features/ai-copilots/knowledge#Back-end-knowledge)
  with RAG.
- Set up [tools](/docs/ready-made-features/ai-copilots/tools), allowing you to
  fill your app with AI-powered
  [actions](/docs/ready-made-features/ai-copilots/tools#Actions),
  [custom components](/docs/ready-made-features/ai-copilots/tools#Custom-components),
  and
  [AI presence](/docs/ready-made-features/ai-copilots/tools#AI-presence-and-streaming).
- Find help on our
  [troubleshooting](/docs/ready-made-features/ai-copilots/troubleshooting) page,
  where we detail common errors, and how to avoid rate limits with
  [fallback models](/docs/guides/how-to-use-fallback-ai-models-in-ai-copilots).

[Let us know](/contact/support) if you have any feedback on the new
documentation, or if there's anything else you’d like to see added.

## Liveblocks AI assistant [#liveblocks-ai-assistant]

We’ve added a multi-purpose AI assistant to our docs and dashboard, built with
[AI Copilots](/ai-copilots), allowing you to ask questions, create projects,
navigate to pages, view your usage, contact support, and much more.

<Figure>
  <MuxVideo
    playbackId="j7bha02NQNRC400WWsCokdSx0285mvh4DfJxf6MlNtRo1I"
    alt="Liveblocks AI assistant"
  />
</Figure>

You can interact with the assistant outside the chat too, for example via
buttons or inputs. Every page and code snippet in our docs has Ask AI buttons if
you get stuck, and we also provide ways to upgrade more easily, by letting AI
write install commands for you.

<Figure>
  <MuxVideo
    playbackId="K4ez201pRP7vA7U01xzqxqnvTOQBDJeqKvPfl02vUEnX2k"
    alt="Interact with the LiveblocksAI assistant from outside the chat"
  />
</Figure>

### How it works

The Liveblocks [`AiChat`](/docs/api-reference/liveblocks-react-ui#AiChat)
component renders our default chat components, with hooks such as
[`useAiChats`](/docs/api-reference/liveblocks-react#useAiChats) and
[`useSendAiMessage`](/docs/api-reference/liveblocks-react#useSendAiMessage) used
to embed additional functionality.

In total, the assistant has 17 different
[tools](/docs/ready-made-features/ai-copilots/tools) at its disposal, giving it
the power to navigate the website, fetch plan information, create projects, and
more. Its
[copilot](/docs/ready-made-features/ai-copilots/copilots#System-prompt) has a
long, detailed prompt for the assistant, filled with example responses, which
directs when each tool should be used.

It also understands all the information on our website using
[back-end knowledge](/docs/ready-made-features/ai-copilots/knowledge#Back-end-knowledge),
which allows you to crawl and ingest the contents of a website. Data about the
current user, page, and team is passed as contextual
[front-end knowledge](/docs/ready-made-features/ai-copilots/knowledge#Front-end-knowledge).

## Dashboard improvements [#dashboard-improvements]

We’ve worked hard to improve the overall user experience of our
[dashboard](/dashboard), making it simpler and clearer how to manage your
projects, rooms, and more. We’ve included lots of new hints and tooltips
throughout.

<Figure>
  <MuxVideo
    playbackId="B8shW7jADwMKGw21wA00vx4TRlRAWb3cuHakKrzPjaps"
    alt="Create project"
  />
</Figure>

One page we’ve taken particular care to improve is the notifications page. To
send Liveblocks notifications outside of your app (e.g. via email, Slack) you
need to use this page to set up each notification channel and webhook. When you
set up a channel, a message is now displayed, letting you know whether a webhook
is configured, offering a shortcut if none has been.

<Figure>
  <MuxVideo
    playbackId="od00zWnQsysMI6sDM8AwZ01iivYRqkXyu68sdDwZ55Pyc"
    alt="Create webhook"
  />
</Figure>

There’s also a new Edit mode and side panel UI for editing your current
notification channels, making it clearer how everything links together. Modify
your settings for the current channel, then publish your changes to complete the
process.

<Figure>
  <MuxVideo
    playbackId="ZRaSCqPl3N8JAW014oAn2U84FdzNljxzJU2vcVwQp4gY"
    alt="Edit notifications"
  />
</Figure>

User experience is important to us at Liveblocks and we’ll continue making
improvements in this area.

## Minor improvements

- Update type definitions for provider models to support GPT-5 variants.
- Add support for web search to `<AiChat />` component.
- Add `showSources`, `showRetrievals` and `showReasoning` props to `<AiChat />`
  component to determine how sources, retrievals and reasoning are displayed
  respectively.
- Disable AI chat composers when AI service is not available.
- Add query filter `subscribed` on the `useThreads` hook.
- Add `useUrlMetadata` hook to get metadata for a given URL.
- Expose `disconnected` status in `useAiChatStatus` to indicate when AI service
  is not available.
- Add query filter `subscribed` on the `room.getThreads` method.
- Update `createAiCopilot` and `updateAiCopilot` to include web search in
  provider options for OpenAI and Anthropic.
- Remove all schema validation related client methods that should no longer be
  used. Schema validation was sunsetted on May 1st, 2025.
- Greatly improved “Notifications” flow, making it much clearer how they're
  linked to webhooks.
  - New “Kinds” tab, allowing you to define batching per kind.
  - See the status of your webhooks from here.
  - Warnings when no webhooks are set up, and shortcuts to get started.
- Improved “Webhooks” page.
  - Set a rate limit for your webhooks when creating them.
  - More detailed error messages when creating webhooks.
  - Better UX on the URL input.
- Improved UX when creating projects
  - New polished project cards displaying more info such as region restrictions.
  - More clarity in project creation dialog boxes.
- Improved team/project selectors with UI polish and better accessibility.
- Improved MAU usage cards showing your team’s personalized limits.
- More clarity in project settings regarding environment and regions not being
  editable.
- Fixed problem downloading examples with `create-liveblocks-app` integration.
- Add `chatId` prop to `RegisterAiKnowledge` to scope knowledge to a specific
  chat, similar to `RegisterAiTool`. This is the same as using the `knowledge`
  prop on `AiChat`.
- Fix issue where `useAiChat()` didn't re-render correctly when chat title gets
  updated.
- Fix issue where `organizationId` was not being passed to the request when
  using `Liveblocks.createRoom()`.
- Add `comments:write` to the list of possible room permissions.
- `LiveMap` and `LiveObject` deletions now report which item got deleted in the
  update notifications. `LiveList` already did this.
- Support numerical operators `gt`, `lt`, `gte`, and `lte` in `room.getThreads`
  metadata query filters.
- Add new hook
  [`useAiChatStatus`](https://liveblocks.io/docs/api-reference/liveblocks-react#useAiChatStatus)
  that offers a convenient way to get the current generation status for an AI
  chat, indicating whether the chat is idle, currently generating contents, and,
  if so, what type of content is currently generating.
- Fixes an issue where `useUnreadInboxNotificationsCount` wasn't returning the
  proper count if there were more than a page of unread notifications.
- Support numerical operators `gt`, `lt`, `gte`, and `lte` in `useThreads`
  metadata query filters.
- Add `responseTimeout` property to `AiChat` to allow customization of the
  default 30 seconds timeout.
- The `title` prop on `AiTool` now accepts `ReactNode`, not just strings.
- Fix a bug where `AiChat` would not always scroll in the same way when sending
  new messages.
- Add new method `Liveblocks.prewarmRoom(roomId, options)`. This method can
  prewarm a room from your back-end, preparing it for connectivity and making
  the eventual connection from the frontend faster.
- Add query filters `roomId` and `kind` on the
  `useUnreadInboxNotificationsCount` hook.
- Add query filters `roomId` and `kind` on the `getInboxNotifications` method.
- Add query filters `roomId` and `kind` on the `useInboxNotifications` hook.
- Rename `budgetToken` to `budgetTokens` in `AnthropicProviderOptions`.
- Fixes a bug where a specific combination of concurrent LiveList mutations
  could break eventual consistency (two clients disagreeing on the final
  document state).
- Only show retrieval and reasoning durations in `AiChat` when they are 3
  seconds or longer.
- Make `AiTool` titles selectable.
- Auto-abort this client's tool calls on page unload to prevent hanging chats.
- Reasoning in `AiChat` now displays how long it took.
- `AiChat` now shows when a copilot is searching its knowledge defined on the
  dashboard, as a "Searching 'What is RAG?'…" indicator. It also displays how
  long it took.
- Add `Duration` primitive to display formatted durations, similar to the
  existing `Timestamp` primitive.
- Better type safety for copilot creation and update options.
- Add missing type export for AI Copilot and knowledge sources.
- Throttle incoming AI delta updates to prevent excessive re-renders during fast
  streaming.
- Optimized partial JSON parser for improved tool invocation streaming
  performance.
- Fixes a Tiptap bug where a comment could not be selected if it was within a
  previously deleted comment.
- Add API reference modal to AI Copilot detail pages, with React, Node.js, and
  REST API snippets to get started quickly.
  - Add `useGroupInfo` hook to use `resolveGroupsInfo` in React, same as
    `useUser` for `resolveUsers`.
- Support group mentions in default components (mentions suggestions dropdowns,
  `Thread`, `Composer`, `InboxNotification`, etc).
- Support group mentions in comments-related components.
- Support group mentions in text editors.
- Add methods to manage groups on Liveblocks (e.g. `createGroup`,
  `getUserGroups`).
- Add `tenantId` parameters to methods that need it when using tenants.
- Mark `getThreadParticipants` as deprecated, use thread subscriptions or
  `getMentionsFromCommentBody` instead.
- Support group mentions in `stringifyCommentBody`, it now accepts a
  `resolveGroupsInfo` option that passes the results to mentions as `group`.
- Support group mentions in email notifications helpers. These functions now
  accept a `resolveGroupsInfo` option that passes the results to mentions as
  `group`.
- Add new `resolveGroupsInfo` resolver to provide information about groups (e.g.
  `name`, `avatar`, etc) similar to `resolveUsers`.
- Support returning group mention suggestions in `resolveMentionSuggestions`.

### Upgrade

To use these latest features, update your packages with:

```bash
npx create-liveblocks-app@latest --upgrade
```

## Contributors

<Contributors
  gitHubUsernames={[
    "jrowny",
    "ctnicholas",
    "pierrelevaillant",
    "nvie",
    "marcbouchenoire",
    "nimeshnayaju",
    "ofoucherot",
    "flowflorent",
  ]}
/>