We’re excited to announce several new features coming to version 0.17:

- [Better TypeScript integration](#better-typescript-integration)
- [React Native support](#react-native-support)
- [Improved LiveList conflict resolution](#improved-livelist-conflict-resolution)
- [New API endpoints](#new-api-endpoints)

## Better TypeScript integration [#better-typescript-integration]

Some of our APIs accept generic types that let you redefine your storage schema
even if it has been initialized differently. This flexibility gives a false
sense of confidence and can lead to confusion.

Our long-term goal is to give you the tools to define your Storage schema to
safely build your app around it and make sure that you can synchronize your
documents to your own database without invalid data.

A great way to start doing this is to rely on TypeScript to define the schema at
the [`Room`](/docs/api-reference/liveblocks-client#Room) level. In this release,
we now let you define your types once in a `liveblocks.config.ts` file—enabling
you to have a clear and scalable data schema at the client level. Here is what
it looks like for React.

```tsx file="liveblocks.config.ts"
import { createClient } from "@liveblocks/client";
import { createRoomContext } from "@liveblocks/react";

const client = createClient({
  /* client options */
});

// Presence represents the properties that will exist on every User in the Room
// and that will automatically be kept in sync. Accessible through the
// `user.presence` property. Must be JSON-serializable.
type Presence = {
  cursor: { x: number; y: number } | null;
  // ...
};

// Optionally, Storage represents the shared document that persists in the
// Room, even after all Users leave. Fields under Storage typically are
// LiveList, LiveMap, LiveObject instances, for which updates are
// automatically persisted and synced to all connected clients.
type Storage = {
  author: LiveObject<{ firstName: string; lastName: string }>;
  // ...
};

export const {
  RoomProvider,
  useMyPresence,
  useObject,
  /* ...all the other hooks you’re using... */
} = createRoomContext<Presence, Storage>(client);
```

The hooks can then be imported from the config file inside your application.

```tsx file="src/index.ts"
import { useMyPresence, useObject, useOthers } from "./liveblocks.config";

// All the hooks are typed without additional generics
const author = useObject("author");
const [{ cursor }] = useMyPresence();
const others = useOthers();
```

With this, you’ll have an even better code completion experience in tools like
VSCode—giving you the confidence that what you’re typing maps to the schema
defined in `liveblocks.config.ts`.

<Figure>
  <figcaption className="sr-only">
    A video showing someone typing in VSCode.
  </figcaption>
  <video autoPlay loop muted playsInline>
    <source
      src="/images/blog/whats-new-in-v0-17-vscode-autocompletion.mp4"
      type="video/mp4"
    />
  </video>
</Figure>

Client-side typing is only the first step; this foundational work will pave the
way for runtime checking and server-side validation.

As of 0.17, we’ve deprecated the use of some previously recommended APIs, to be
able to offer better type inference and auto-completion going forward. We’ve
kept these breaking changes as small as possible, and we’ve written a
[step-by-step guide to help you migrate](/docs/guides/upgrading/0.17). If you’re
stuck, please reach out to us on
[GitHub](https://github.com/liveblocks/liveblocks), and we’ll lend you a hand!

## React Native support [#react-native-support]

With the release of 0.17, we’re also bringing React Native support! Under the
hood, Liveblocks relies on
[WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API),
[fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API),
[atob](https://developer.mozilla.org/en-US/docs/Web/API/atob), and
[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
This makes it technically possible to use our APIs with all kinds of
technologies—including [React Native](https://reactnative.dev/).

<Figure>
  <Image
    src="/images/blog/react-native-example.png"
    alt="React Native To-do List"
    width={672}
    height={400}
    quality={90}
  />
</Figure>

Please take a look at our
[API reference](/docs/api-reference/liveblocks-client#createClientReactNative)
to learn how to use Liveblocks packages with React Native. You can also check
out this
[open-source React Native multiplayer to-do list example](https://github.com/liveblocks/liveblocks/tree/main/examples/react-native-todo-list)
if you’d prefer to learn that way.

We’re excited to see what kind of native app you’ll build with Liveblocks!

## Improved LiveList conflict resolution [#improved-livelist-conflict-resolution]

In previous versions, there were some issues related to the way we handled data
conflicts when multiple people updated the same lists. This rarely occurred, but
at Liveblocks we’re committed to building the most reliable APIs possible.

The Liveblocks server now appropriately resolves conflicts when multiple people
add items to a [`LiveList`](/docs/api-reference/liveblocks-client#LiveList)
simultaneously.

<Figure>
  <figcaption className="sr-only">
    An animation showing two users adding elements to a list simultaneously.
  </figcaption>
  <video autoPlay loop muted playsInline>
    <source
      src="/images/blog/whats-new-in-v0-17-conflict-lists.mp4"
      type="video/mp4"
    />
  </video>
</Figure>

To make sure this continues to work smoothly, we’ve improved our test coverage:
in addition to our
[fuzz tests](https://twitter.com/guillaume_slls/status/1442841522202886146), we
now have end-to-end tests to consistently reproduce these scenarios, including
the one highlighted below. If you’re curious, feel free to check them out
directly on
[GitHub](https://github.com/liveblocks/liveblocks/blob/main/packages/liveblocks-client/e2e/list.test.ts#L9-L28).

```ts
test(
  "remote insert conflicts with another insert",
  prepareTestsConflicts(
    {
      list: new LiveList(),
    },
    async ({ root1, root2, wsUtils, assert }) => {
      root1.get("list").push("A");
      root2.get("list").push("B");

      await wsUtils.flushSocket1Messages();

      assert({ list: ["A"] }, { list: ["A", "B"] });

      await wsUtils.flushSocket2Messages();

      assert({ list: ["A", "B"] });
    }
  )
);
```

Building a stable multiplayer infrastructure implies having great test
coverage—we’re excited about these improvements and will continue to invest in
this area.

## New API endpoints [#new-api-endpoints]

More additions in 0.17 are the new API endpoints, unlocking all kinds of new
experiences for developers. The first one allows you to
[get connected users in a room](/docs/api-reference/rest-api-endpoints#GetRoomUsers),
and the second one allows you to
[get the rooms that have been created](/docs/api-reference/rest-api-endpoints#GetRooms).

<Figure>
  <Image
    src="/images/blog/gif-room-lobby@2x.gif"
    alt="Lobby enabling automatic room assignment"
    width={672}
    height={400}
    quality={90}
  />
</Figure>

Amongst other things, **these endpoints enable developers to create what we’re
calling lobby-based multiplayer experiences**. In these lobbies, visitors can
automatically be assigned to different rooms based on how full they are.

This is especially useful for multiplayer landing pages and websites that get a
lot of visitors at once: instead of filling up one room quickly and not enabling
others to participate in the interactive multiplayer experience, they now can
get automatically assigned to rooms as soon as they land on the page.

This is something we’re experimenting with at the moment and is yet to be
properly documented. Here is a
[proof-of-concept built with Next.js, Redis, and Liveblocks](https://github.com/liveblocks/lobby-demo)
to show you how to set it up for your own landing page. If this is something
you’d be interested in or would like to contribute to, please reach out.

## Contributors

A big thank you to all our contributors! We wouldn’t have made it here without
your support and feedback. This month, we want to send a special shout-out to
[@Vinod_Santharam](https://twitter.com/Vinod_Santharam) for the React Native
integration, and [@ofoucherot](https://github.com/ofoucherot) for the conflict
resolution stability.

And that’s all, folks! Remember to check out the
[changelog](https://github.com/liveblocks/liveblocks/blob/main/CHANGELOG.md#v0170)
for the full release notes, and see you soon for 0.18!