Skip to content

pluv-io/pluv

Repository files navigation

pluv.io

TypeSafe Primitives for a Realtime Web

npm @pluv/io GitHub Commitizen friendly TypeScript

pluv.io - Open source multiplayer APIs, powered by TypeScript | Product Hunt

πŸ’• Inspired by trpc πŸ’• yjs πŸ’•
and Cloudflare Workers πŸ’•

Intro

pluv.io allows you to more easily build realtime multiplayer experiences with a fully typesafe API and powerful abstractions as primitives, so that you can focus on building for your end users.

Self-host on Cloudflare Workers or Node.js; or get started on the pluv.io network.

Preview

Create your pluv.io backend

// backend
const io = createIO(
  platformNode({
    context: () => ({ db }),
    crdt: yjs,
  })
);

export const ioServer = io.server({
  getInitialStorage: async ({ context: { db }, room }) => {
    return await db.room
      .findUnique({ where: { id: room } })
      .then((result) => result?.encodedState ?? null);
  },
  router: io.router({
    sendGreeting: io.procedure
      .input(z.object({ message: z.string() }))
      .broadcast(({ message }) => ({
        receiveGreeting: { message }
      }))
  })
});

Create your frontend client with your backend types

// frontend
const types = infer((i) => ({ io: i<typeof ioServer> }));
const io = createClient({
  types,
  initialStorage: yjs.doc((t) => ({
    messages: t.array<string>("messages"),
  })),
  presence: z.object({
    selectionId: z.string().nullable()
  })
});

const {
  event,
  useBroadcast,
  useMyPresence,
  useOthers,
  useStorage
} = createBundle(io);

Use powerful primitives to build realtime features

// react
event.receiveGreeting.useEvent(({ data }) => { /* ... */});
//                                ^? const data: { message: string }

const broadcast = useBroadcast();

broadcast.sendGreeting({ message: "hello world" });
//        ^? const sendGreeting: (data: { message: string }) => void

const [mySelection, update] = useMyPresence((presence) => {
//     ^? const mySelection: string | null
  return presence.selectionId;
});

const others = useOthers((others) => {
//    ^? const others = string[]
  return others.map((other) => other.presence.selectionId);
});

const [
  messages,
// ^? const messages: string[] | null
  sharedType
// ^? YArray<string> | null
] = useStorage("messages");

Documentation

The full documentation is available at pluv.io.

Features

  • βœ… Automatic type-safety
  • βœ… Basic events
  • βœ… Rooms
  • βœ… Authentication
  • βœ… Awareness + Presence
  • βœ… CRDTs
  • ⬜ Studio (admin & developer panel)

Runtimes

Frontends Frameworks

Packages

Credits

This software uses the following open source tooling and libraries:

License

MIT