Liveblocks 1.12 introduces additions to Comments and example updates.

- [Advanced thread and room filtering](#advanced-thread-and-room-filtering):
  Filter with queries on client and server.
- [Custom notifications alpha](#custom-notifications-alpha): Send custom
  notifications to InboxNotification.
- [Inbox notification thread hook](#inbox-notification-thread-hook): Get thread
  data that’s part of a notification.
- [Comments canvas example](#canvas-comments-example): Add draggable comments to
  your application.
- [Next.js Starter Kit update](#nextjs-starter-kit-update): Uses `/app`
  directory, and is much simpler.

## Upgrade now

Upgrade now by updating each Liveblocks package to the `@latest` version.

```bash
 npm install @liveblocks/client@latest @liveblocks/react@latest @liveblocks/react-comments@latest liveblocks/node@latest
```

There are no breaking changes in Liveblocks 1.12.

## Advanced thread and room filtering [#advanced-thread-and-room-filtering]

Liveblocks 1.12 introduces query-based thread filtering to
[Comments](/comments), allowing you to create advanced UI components for
filtering threads by their metadata.

<Figure highlight={false}>
  <Image
    src="/images/blog/liveblocks-1-12/filters.jpg"
    alt="Showing comments associated with specific categories"
    width={672}
    height={448}
    quality={95}
  />
</Figure>

To enable filtering by metadata, pass a `query` option to
[`useThreads`](/docs/api-reference/liveblocks-react#useThreads). Only threads
that match the query will be returned, and you can even use a `startsWith`
option to find partial metadata string matches. In this example, we’re filtering
for unresolved threads that are assigned to a specific string.

```tsx highlight="6-11"
import { useThreads } from "../liveblocks.config";

function Component() {
  const { threads } = useThreads({
    query: {
      metadata: {
        resolved: false,
        assignedTo: {
          startsWith: "liveblocks:design:",
        },
      },
    },
  });

  // ...
}
```

Filtering is also enabled on the server using
[`liveblocks.getThreads`](/docs/api-reference/liveblocks-node#get-rooms-roomId-threads),
working in the exact same way.

```ts highlight="8-17"
import { Liveblocks } from "@liveblocks/node";

const liveblocks = new Liveblocks({
  secret: "{{SECRET_KEY}}",
});

export async function POST() {
  const { data: threads } = await getThreads({
    query: {
      metadata: {
        resolved: false,
        assignedTo: {
          startsWith: "liveblocks:design:",
        },
      },
    },
  });

  // ...
}
```

If you’re using our REST API directly, you can
[filter using our new query language](/docs/guides/how-to-filter-threads-using-query-language).

### Advanced room filtering

Liveblocks 1.12 also enables advanced room filtering on the server, allowing you
to fetch any rooms that match a specific
[room ID naming pattern](/docs/authentication/access-token#Naming-pattern). In
this example we’re filtering for `"whiteboard"` rooms, and then using
`startsWith` to only match rooms with IDs that begin with `"liveblocks:"`

```ts highlight="10-15"
import { Liveblocks } from "@liveblocks/node";

const liveblocks = new Liveblocks({
  secret: "{{SECRET_KEY}}",
});

export async function POST() {
  const { data: rooms } = liveblocks.getRooms({
    query: {
      roomId: {
        startsWith: "liveblocks:",
      },
      metadata: {
        type: "whiteboard",
      },
    },
  });

  // ...
}
```

If you’re using our REST API directly, you can
[filter using our new query language](/docs/guides/how-to-filter-rooms-using-query-language).

## Custom notifications alpha [#custom-notifications-alpha]

When using Comments, you can choose to render relevant
[inbox notifications](https://liveblocks.io/docs/products/comments/notifications)
for users when threads update. We’re extending these notifications, allowing you
to send any kind of custom notification, and we’ve just released the alpha in
Liveblocks 1.12.

<Figure highlight={false}>
  <Image
    src="/images/blog/liveblocks-1-12/custom-notification.jpg"
    alt="Custom notification inside in-app notification inbox"
    width={672}
    height={448}
    quality={95}
  />
</Figure>

To send a custom notification, call
[`liveblocks.triggerInboxNotification`](/docs/api-reference/liveblocks-node#post-inbox-notifications-trigger)
on the server. Here’s an example that notifies users about a file upload.

```ts
await liveblocks.triggerInboxNotification({
  kind: "$fileUploaded",
  userId: "pierre@example.com",
  subjectId: "file-upload-6f9sg7...",

  activityData: {
    name: "pitch-deck.pdf",
    uploadedBy: "steven@example.com",
    url: "https://example.com/pitch-deck.pdf",
  },
});
```

Then in React, you can render a custom notification for `$fileUploaded`,
accessing the custom `activityData` that was set.

```tsx
<InboxNotification kinds={{ $fileUploaded: FileUploadedNotification }} />
```

```tsx
function FileUploadedNotification(props) {
  const activityData = props.inboxNotification.activities[0].data;
  const { user } = useUser(activityData.uploadedBy);

  return (
    <InboxNotification.Custom
      title={`${user.name} uploaded a new file`}
      aside={<InboxNotification.Avatar userId={user.id} />}
      {...props}
    >
      <a href={activityData.url}>🗎 {activityData.name}</a>
    </InboxNotification.Custom>
  );
}
```

We generally recommend using
[`<InboxNotification.Custom>`](/docs/api-reference/liveblocks-react-ui#InboxNotification.Custom)
to render notifications, as it allows you to place your content in slots that
work with the existing design system. However, you can also use completely
custom styling, should you choose.

```tsx
<InboxNotification
  kinds={{
    $fileUploaded: (props) => {
      const { name, url } = props.inboxNotification.activities[0].data;
      return <a href={url}>{name} has been uploaded</a>;
    },
  }}
/>
```

We’ll be sharing more about custom notifications soon, as we continue to work on
it. Make sure to join our [Discord server](https://liveblocks.io/discord) or
follow us on [Twitter](https://twitter.com/liveblocks) and
[LinkedIn](https://www.linkedin.com/company/liveblocks) for updates and upcoming
content.

## Inbox notification thread hook [#inbox-notification-thread-hook]

An advanced use case for inbox notifications is building your own custom
components for _thread_ notifications. Previously for these components, you’d
have to implement your own logic to fetch thread information, but we’ve now
created a new
[`useInboxNotificationThread`](/docs/api-reference/liveblocks-react#useInboxNotificationThread)
hook which will handle this for you.

```tsx
import { useInboxNotificationThread } from "../liveblocks.config";

function Component({ inboxNotification }) {
  const thread = useInboxNotificationThread(inboxNotification.id);

  // { id: "th_d75sF3...", metadata: { ... }, ... }
  console.log(thread);

  // Use your thread data
  // ...
}
```

## Canvas Comments example [#canvas-comments-example]

We’ve built a new Comments example detailing how to build a canvas with
draggable threads. With a quick copy-and-paste, you can add this to your
application—the code and a live demo are available in our
[examples gallery](/examples/canvas-comments/nextjs-comments-canvas)!

<Figure>
  <figcaption className="sr-only">A showcase of the new example.</figcaption>
  <video autoPlay loop muted playsInline>
    <source
      src="/images/blog/liveblocks-1-12/canvas-comments.mp4"
      type="video/mp4"
    />
  </video>
</Figure>

We also have a similar, more complex example, that allows you to
[pin threads to HTML elements](/examples/overlay-comments/nextjs-comments-overlay).

## Next.js Starter Kit update [#nextjs-starter-kit-update]

Our [Next.js Starter Kit](/starter-kit) has been completely rewritten and now
uses the Next.js `/app` directory. Just to recap, the Next.js Starter Kit is a
great starting point when building your own collaborative application, and
highlights how to use every aspect of Liveblocks.

<YouTube id="pA2nQXzswhs" />

Previously, a number of files were necessary to synchronize types and
functionality between client, server, and API endpoints, but thanks to
[server actions](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations),
type-safe functions now work on both server and client.

```ts
import { getDocument } from "@/lib/actions";

// Can be used in both browser and Node.js
const { data, error } = await getDocument({
  documentId: "my-document-id",
});
```

Not only has this update greatly shrunk the codebase, but the main bundle size
is [almost 50% smaller too](https://github.com/liveblocks/liveblocks/pull/1538).
To download and deploy the Next.js Starter Kit, run the following command.

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

You can also try a [live demo](https://nextjs-starter-kit.liveblocks.app).

## Upgrade

There are no breaking changes in this update, and you can start using the new
features now. Update every Liveblocks package in your project to the `@latest`
version to get started.

```bash
 npm install @liveblocks/client@latest @liveblocks/react@latest @liveblocks/react-comments@latest liveblocks/node@latest
```

If you’d like to add Comments to your application, make sure to check out our
guides and examples.

- [Get started with Comments](/docs/get-started/nextjs-comments)
- [Comments examples](/examples/browse/comments)
- [Comments guides](/docs/guides?topics=comments)

## Contributors

Huge thanks to everyone who contributed, and specifically to
[Adrien Gaudon](https://x.com/adigau31),
[Florent Lefebvre](https://x.com/florentpml),
[Guillaume Salles](https://x.com/guillaume_slls),
[Marc Bouchenoire](https://x.com/marcbouchenoire),
[Nimesh Nayaju](https://x.com/nayajunimesh),
[Olivier Foucherot](https://www.linkedin.com/in/olivier-foucherot) for their
work on Comments and Notifications. Keep checking the
[changelog](https://github.com/liveblocks/liveblocks/blob/main/CHANGELOG.md) for
the full release notes—see you next time!