Upgrading - Upgrading to 1.0

Liveblocks 1.0 is our first major release, marking the end of the beta period for storage and conflict-free data types. This release includes improvements to our pricing model that make billing more predictable. Additionally, we have vastly improved the ability to animate cursors at up to 60fps by updating the throttle option in createClient. The primary change you should note is the transition to making the userId mandatory in the authorize option. This change is in line with our new pricing model.

Let’s take a look!

Upgrading steps by package

@liveblocks/node

To update @liveblocks/node to 1.0, run the following command using your preferred package manager:

$npm install @liveblocks/node@1.0.0

Update the authorize option

We have updated the authorize method to make userId mandatory. This change ties into our new pricing model, which is based on Monthly Active Users (MAU) instead of connections. We use userId to track MAU associated with a Liveblocks account.

import { authorize } from "@liveblocks/node";
// Replace this key with your secret key provided at// https://liveblocks.io/dashboard/projects/{projectId}/apikeysconst secret = "sk_prod_xxxxxxxxxxxxxxxxxxxxxxxx";
export default async function auth(req, res) { /** * Implement your own security here. * * It’s your responsibility to ensure that the caller of this endpoint * is a valid user by validating the cookies or authentication headers * and that it has access to the requested room. */ const room = req.body.room; const response = await authorize({ room, secret, // Corresponds to the UserMeta[id] type defined in liveblocks.config.ts userId: "123", // Required groupIds: ["456"], // Optional userInfo: { // Optional, corresponds to the UserMeta[info] type defined in liveblocks.config.ts name: "Ada Lovelace", color: "red", }, }); return res.status(response.status).end(response.body);}

If you do not use the authorize function because you are using the public API key method, a cookie will be set in the browser when a user connects to a room. This cookie will be used to track MAU associated with a Liveblocks account and will expire after 30 days.

Authorize endpoint

If you do not use the authorize function, but call the authorize endpoint with a secret key instead, you should pass the userId even though it is not mandatory on the API level because the userID will be used for MAU. Set the Authorization: Bearer header to your secret key.

POST https://api.liveblocks.io/v2/rooms/{roomId}/authorize

Set the following the request body:

{  "userId": "user123",  "groupIds": [    "g1",    "g2"  ],  "userInfo": {    "name": "bob",    "colors": [      "blue",      "red"    ]  }}

Improvements

We added additional features to Webhooks, enhancements to the Room class, and more. You can review the release notes for more details.

@liveblocks/client

To update @liveblocks/client to 1.0, run the following command using your preferred package manager:

$npm install @liveblocks/client@1.0.0

Improvements to throttle allow animation of up to 60fps

You can now specify the throttle option in createClient that can go as low as 16ms. If not set, the default value is 100ms.

import { createClient } from "@liveblocks/client";
const client = createClient({ /* ... other options ... */ throttle: 16,});

You can see the marked improvement in the animation from 80ms (original limit) to 16ms in this tweet. If you want to try it out for yourself, check out live cursors example.

New methods available on the Room class

We added new methods to the Room class that you can use to obtain the storage status of a room, subscribe to storage status changes, or reconnect to a room whenever necessary. You can also use the Liveblocks DevTools extension to visualize real-time changes to storage while implementing these changes.

Use room.getStorageStatus to retrieve the storage status of a room. The statuses are:

  • not-loaded: Initial state when entering the room.
  • loading: Once the storage has been requested via room.getStorage().
  • synchronizing: When some local updates have not been acknowledged by Liveblocks servers.
  • synchronized: Storage is in sync with Liveblocks servers.

Use room.subscribe to subscribe to storage status changes. This method returns an unsubscribe function.

room.subscribe("storage-status", (status) => {  // Implement your logic here  switch (status) {    case "not-loaded":      break;    case "loading":      break;    case "synchronizing":      break;    case "synchronized":      break;    default:      break;  }});

You can use room.reconnect() to close the room connection and try to reconnect.

@liveblocks/node

Webhooks enhancements

We have added two new events to our Webhooks functionality: RoomCreatedEvent and RoomDeletedEvent. We have also added a WebhookHandler class to make it easier to verify event requests from Liveblocks’ Webhooks functionality. It also provides fully typed WebhookEvents.

import { WebhookHandler } from "@liveblocks/node";
const webhookHandler = new WebhookHandler(process.env.SECRET);
const event = webhookHandler.verifyRequest({ headers: req.headers, rawBody: req.body,});

Verification of events is critical to ensure that the events are coming from Liveblocks and not from a malicious source. Check out our Webhooks guide for more details.

That’s it!

If you have issues with these new patterns and need help, please let us know by email or by joining our Discord community! We’re here to help!