At Liveblocks, our mission is to empower companies and developers to create
amazing document‑based collaborative products to enable people to feel more
connected and work better together.

The first foundational step to accomplish this mission was about distributing
tools and APIs that made it dead simple for developers to build
[multiplayer editor experiences](/showcase). What do we mean by that? Think of
the Figma’s, Notion’s, and Pitch’s of the world.

But outside of their collaborative editors, what do all those products also have
in common? They have a great document/file browsing experience, a smooth
share/invite flow driving organic product‑led growth, custom group/user
permissions, and more!

<Slideshow
  slides={[
    {
      width: 616,
      height: 394,
      imageUrl: "/images/blog/rooms-overview-share/figma-overview.png",
      caption:
        "Figma file browsing experience automatically updates as people join and make changes to files.",
    },
    {
      width: 616,
      height: 394,
      imageUrl: "/images/blog/rooms-overview-share/figma-share.png",
      caption:
        "People can easily be invited to Figma files by sharing the URL or using their share dialog.",
    },
    {
      width: 616,
      height: 394,
      imageUrl: "/images/blog/rooms-overview-share/notion-overview.png",
      caption:
        "In Notion, documents are listed in both the sidebar and the documents themselves.",
    },
    {
      width: 616,
      height: 394,
      imageUrl: "/images/blog/rooms-overview-share/notion-share.png",
      caption:
        "People can easily be invited to Notion files by sharing the URL or using their share dialog.",
    },
    {
      width: 616,
      height: 394,
      imageUrl: "/images/blog/rooms-overview-share/pitch-overview.png",
      caption:
        "Pitch document browsing experience automatically updates as people join and make changes to presentations.",
    },
    {
      width: 616,
      height: 394,
      imageUrl: "/images/blog/rooms-overview-share/pitch-share.png",
      caption:
        "People can easily be invited to Pitch presentations by sharing the URL or using their share dialog.",
    },
  ]}
/>

Today, we’re excited to announce a new set of REST APIs that will help you build
those critical experiences too. The possibilities are endless, but here are a
few common collaborative UI patterns we’d like to highlight today:

- [Share dialogs with permissions](#share-dialogs-with-permissions)
- [Filterable and paginated overview pages](#filterable-and-paginated-overview-pages)
- [Groups with permissions](#groups-with-permissions)

## Share dialogs with permissions

The first major improvement is that rooms (or documents in this context) can
have different permission types assigned at three different levels: default,
groups, and users. We designed this solution to be easy-to-use, yet powerful and
flexible, enabling companies to design and build permission systems that fit
their unique requirements.

For instance, you can now easily add a world-class share dialog that will
organically drive more people to your product.

<Figure>
  <Image
    src="/images/blog/managing-rooms/rooms-share-dialog.png"
    alt="Share dialog illustration"
    quality={90}
    width={1640}
    height={824}
  />
</Figure>

To create the invitation system above, first we need to give a user a `userId`
when [authenticating](/docs/guides/authentication), for example within
`authorize` from `@liveblocks/node`.

```js highlight="3"
import { authorize } from "@liveblocks/node";
const response = await authorize({
  userId: "ellen@acme.inc",
  // ...
});
```

Then we can use the
[update room API](/docs/api-reference/rest-api-endpoints#post-rooms-roomId) to
assign permissions to that user.

```ts highlight="6"
const roomId = "my-room-name";
fetch(`https://api.liveblocks.io/v2/rooms/${roomId}`, {
  method: "POST",
  body: JSON.stringify({
    usersAccesses: {
      "ellen@acme.inc": ["room:write"],
    },
  }),
});
```

To check a user’s assigned permission types for this room, we can then use the
[get room API](/docs/api-reference/rest-api-endpoints#get-rooms-roomId) and
check `usersAccesses`.

```ts
const roomId = "my-room-name";
const url = `https://api.liveblocks.io/v2/rooms/${roomId}`;
const response = await fetch(url);
const room = await response.json();

// { "ellen@acme.inc": ["room:write"] }
console.log(room.data.usersAccesses);
```

The invitation system can also be extended to groups of people too, for instance
you could set permissions for the "engineering" group. To do this, first give
users their groups when authenticating.

```js highlight="4"
import { authorize } from "@liveblocks/node";
const response = await authorize({
  userId: "ellen@acme.inc",
  groupIds: ["engineering"],
  // ...
});
```

Then, give the "engineering" group `"room:read"` and `"room:presence:write"`
access to the document.

```ts highlight="6"
const roomId = "my-room-name";
fetch(`https://api.liveblocks.io/v2/rooms/${roomId}`, {
  method: "POST",
  body: JSON.stringify({
    groupsAccesses: {
      engineering: ["room:read", "room:presence:write"],
    },
  }),
});
```

The engineering group now has access to view the room, and to edit their
presence (which can be used to display an online avatar).

To check if a user only has read-only access to storage in your app, the
`isReadOnly` boolean can be also retrieved from `others` or `self`.

```ts
// Vanilla
const { isReadOnly } = room.getSelf();

// React
const selfIsReadOnly = useSelf((me) => me.isReadOnly);
```

## Filterable and paginated overview pages

With this update, rooms can also have custom metadata associated with them,
enabling you to build filterable and paginated overview pages.

For instance, if you have different document types in your product, it is now
easy to expose those types as a filter—making it easy for people to find what
they’re looking for.

<Figure>
  <video autoPlay loop muted playsInline>
    <source
      src="/images/blog/managing-rooms/rooms-type-metadata.mp4"
      type="video/mp4"
    />
  </video>
</Figure>

One way to edit metadata is to use the
[create room API](/docs/api-reference/rest-api-endpoints#post-rooms). In this
example, we’re creating a new room with a custom `type` metadata, and setting it
to "whiteboard".

```tsx
fetch("https://api.liveblocks.io/v2/rooms", {
  method: "POST",
  body: JSON.stringify({
    id: "room-id",
    defaultAccesses: [],
    metadata: {
      type: "whiteboard",
    },
  }),
});
```

We can then use
[get rooms API](/docs/api-reference/rest-api-endpoints#get-rooms) to retrieve a
list of rooms containing the "whiteboard" type.

```tsx
const metadata = "metadata.type=whiteboard";
const url = `https://api.liveblocks.io/v2/rooms?${metadata}`;
const response = await fetch(url);
const rooms = await response.json();
```

And if you have hundreds of documents created, Liveblocks automatically takes
care of pagination by returning the `nextPage` URL in the response—making it
easy to fetch the next page by either clicking on a button or some sort of
infinite scrolling behavior.

```json highlight="2"
{
  "nextPage": "/v2/rooms?startingAfter=W1siaWQiLCJVRzhWYl82SHRUS0NzXzFvci1HZHQiXSxbImNyZWF0ZWRBdCIsMTY2MDAwMDk4ODEzN11d",
  "data": [
    {
      "type": "room",
      "id": "room-id",
      "lastConnectionAt": "2022-09-22T10:23:15.281Z",
      "createdAt": "2022-09-22T10:23:15.281Z",
      "metadata": {
        "type": "whiteboard"
      },
      "defaultAccesses": ["room:write"]
    }
    // more rooms data would show here
  ]
}
```

## Groups with permissions

With our new API endpoints, you can also create fully dedicated views for
groups. Groups are a common pattern in seat-based collaborative products and are
often used to organise documents for different teams and projects.

For instance, if you want to enable your users to configure groups, you could
easily list them in side panel in your product overview page.

<Figure>
  <video autoPlay loop muted playsInline>
    <source
      src="/images/blog/managing-rooms/rooms-groups.mp4"
      type="video/mp4"
    />
  </video>
</Figure>

We’d then use the
[get rooms API](/docs/api-reference/rest-api-endpoints#get-rooms) to retrieve a
list of rooms the group has access to.

```tsx
const groupId = "engineering";
const url = `https://api.liveblocks.io/v2/rooms?groupIds=${groupId}`;
const response = await fetch(url);
const rooms = await response.json();
```

## Contributors

This month, we want to send a special shout-out to
[Vinod Santharam](https://twitter.com/Vinod_Santharam) and
[Florent Lefebvre](https://github.com/FlowFlorent) for their contribution. If
you want to learn more about all the API endpoints we released, please check the
[API Reference](/docs/api-reference/rest-api-endpoints). See you soon for the
next update!