🎉 pluv.io is now stable! Read our announcement here

Create Client

Generally, it is recommended to use framework-specific bindings for your particular UI framework such as @pluv/react. However, if your selected framework is not yet supported, you can create a framework-agnostic pluv.io client to add automatic type-safe realtime to your app right away.

Installation

To install pluv.io for your framework-agnostic frontend, we will install the following packages from pluv.io:

PurposeLocationInstall command
Call and listen to events. Interact with shared storageClientnpm install @pluv/client
yjs CRDTBothnpm install @pluv/crdt-yjs

Installation Example

Here is an example installation for npm for you to copy:

# For the frontend
npm install @pluv/client
# Client peer dependencyes
npm install zod

# Optional if you wish to use CRDT storage
# For storage capatilities
npm install @pluv/crdt-yjs
# Storage peer dependencies
npm install yjs

Creating a PluvClient

Note: This example assumes that you've already created a backend pluv.io instance. Refer to the quickstart to learn more.

// frontend/io.ts

import { createClient, infer } from "@pluv/client";
import { yjs } from "@pluv/crdt-yjs";
import { z } from "zod";

// Use a type import to avoid including the code in your frontend
import type { ioServer } from "./server/pluv-io";

// Connect your `ioServer` type to the client via `infer`
// Note this is declared outside of `createClient` to workaround
// TypeScript inferrence limitations
const types = infer((i) => ({ io: i<typeof ioServer> }));
export const client = createClient({
  types,
  // Optional: Define the initial storage for rooms. This will set
  // the types for storage when using it in your application. Don't
  // worry about the value, as this can be overwritten when creating
  // a room via `client.createRoom`.
  initialStorage: yjs.doc((t) => ({
    messages: t.array<string>("messages", []),
  })),
  // Optional: Define your presence schema
  presence: z.object({
    selectionId: z.string().nullable(),
  }),

  // Optional: Provide additional data at the point of connecting to
  // to the room for use in `publicKey`, `wsEndpoint` or `authEndpoint`.
  // This is particularly useful for Cloudflare Pages where accessing
  // environment variables can be difficult
  metadata: z.object({
    secret: z.string(),
  }),

  // Required if you are using `@pluv/platform-pluv`: This is the
  // publishable-key that was created for your project on pluv.io
  publicKey: ({ metadata }) => "pk_...",

  // Optional: If a `publicKey` is provided, the `PluvRoom` will
  // automatically point to the pluv.io network. However, this
  // can be provided manually if you are self-hosting pluv.io
  wsEndpoint: ({ metadata, room }): string => {
    // Specify the ws endpoint to connect to
    return `ws://localhost:3000/api/room?room=${room}`;
  },

  // Required if `authorize` was specified on `createIO`: This is
  // the endpoint where you've defined your own authorization
  // for your room's participants
  authEndpoint: ({ metadata, room }) => {
    // This can either return a url string, or an object
    // containing a url and options (fetch options) if
    // you need to customize the API request
    return `https://localhost:3000/api/pluv/auth?room=${room}`;
  },
});