TypesafeReal-Time APIsfor |
Multiplayer APIs powered-by TypeScript inference end-to-end
Multiplayer made easy
Pluv provides powerful utilities to make building complex multiplayer experiences easier.
TurnWhiteBlack
1.e4
Type-safety
Get auto-completion and in-code errors with end-to-end type-safety.
Multi-runtime
Build for either Cloudflare Workers or Node.js runtimes.
Yjs CRDT
Edit shared data and documents with the Yjs ecosystem.
Presence
Display user selections with per-user presence states.
Authentication
Add your own custom authentication rules to rooms.
Broadcast
Broadcast custom events to connected clients in the same room.
Simple-to-use APIs
Configure your server and client to unlock intuitive APIs that allow you to focus on your end-user experience.
jane
Drag the boxes
john
Drag the boxes
1import {2 usePluvMyPresence,3 usePluvOthers,4 usePluvStorage,5} from "client/pluv";6import type { FC } from "react";78export const Room: FC = () => {9 // Get data and yjs shared type for mutations10 const [boxes, sharedType] = usePluvStorage("boxes");11 // { first: { x: -56, y: 0 },12 // second: { x: 56, y: 0 } }1314 // Observe and update your selection15 const [selection, setPresence] = usePluvMyPresence((me) => me.selection);16 setPresence({ selection: "first" });1718 // Get selections of other users19 const selections = usePluvOthers((others) => {20 return others.map((other) => other.presence.selection);21 });2223 // return ...24};
End-to-end Type-Safety
Get intellisense and autocomplete, so you can move fast and catch errors in development
1// server/pluv.ts23import { createIO } from "@pluv/io";4import { platformCloudflare } from "@pluv/platform-cloudflare";5import { z } from "zod";67// Create your PluvIO server8const io = createIO({9 platform: platformCloudflare(),10})11.event("EMIT_FIREWORK", {12 input: z.object({ color: z.string() }),13 resolver: ({ color }) => ({14 FIREWORK_EMITTED: { color },15 }),16})17.event("SEND_MESSAGE", {18 // Set input validator and type19 input: z.object({}),20 // Set output value and type21 resolver: ({}) => ({}),22});
1// client/Room.tsx23import { usePluvBroadcast, usePluvEvent } from "client/pluv";4import { FC, useCallback, useState } from "react";56export const Room: FC = () => {7const [messages, setMessages] = useState<string[]>([]);89// Listen to new messages from the server10// Get types from the SEND_MESSAGE resolver output11usePluvEvent("MESSAGE_RECEIVED", ({}) => {12 setMessages((prev) => [...prev]);13});1415const broadcast = usePluvBroadcast();1617const onSubmit = useCallback((message: string) => {18 // Broadcast to all users19 // Get types from the SEND_MESSAGE zod input20 broadcast("SEND_MESSAGE", {});21}, [broadcast]);2223// return ...24};