TL;DR
PartyKit is a platform for building real-time, collaborative, multiplayer applications. It runs on Cloudflare's edge network with a generous free tier — perfect for chat, cursors, games, and collaborative editing.
What Is PartyKit?
PartyKit makes multiplayer easy:
- Edge-first — runs on Cloudflare Workers globally
- Room-based — each "party" is a stateful room
- Hibernation — WebSocket connections stay alive even when idle
- Durable Objects — state persists between connections
- Free tier — 100K requests/day, unlimited connections
- Framework-agnostic — works with any frontend
Quick Start
npm create partykit@latest my-app
cd my-app
npx partykit dev
Server (party/index.ts)
import type * as Party from "partykit/server";
export default class ChatRoom implements Party.Server {
messages: string[] = [];
constructor(readonly room: Party.Room) {}
onConnect(conn: Party.Connection) {
// Send chat history to new connections
conn.send(JSON.stringify({ type: "history", messages: this.messages }));
}
onMessage(message: string, sender: Party.Connection) {
const data = JSON.parse(message);
this.messages.push(data.text);
// Broadcast to everyone in the room
this.room.broadcast(
JSON.stringify({ type: "message", text: data.text, from: sender.id }),
[sender.id] // exclude sender
);
}
onClose(conn: Party.Connection) {
this.room.broadcast(
JSON.stringify({ type: "leave", userId: conn.id })
);
}
}
Client
import PartySocket from "partysocket";
const socket = new PartySocket({
host: "my-app.username.partykit.dev",
room: "my-chat-room",
});
socket.addEventListener("message", (event) => {
const data = JSON.parse(event.data);
if (data.type === "message") {
console.log(`${data.from}: ${data.text}`);
}
});
socket.send(JSON.stringify({ text: "Hello everyone!" }));
Live Cursors Example
// Server
export default class CursorRoom implements Party.Server {
cursors = new Map<string, { x: number; y: number }>();
onMessage(message: string, sender: Party.Connection) {
const cursor = JSON.parse(message);
this.cursors.set(sender.id, cursor);
this.room.broadcast(message, [sender.id]);
}
onClose(conn: Party.Connection) {
this.cursors.delete(conn.id);
this.room.broadcast(JSON.stringify({ type: "leave", id: conn.id }));
}
}
PartyKit vs Alternatives
| Feature | PartyKit | Socket.IO | Liveblocks | Pusher |
|---|---|---|---|---|
| Free tier | 100K req/day | Self-host | 1K MAU | 200K msg/day |
| Edge deployment | ✅ Cloudflare | ❌ | ✅ | ✅ |
| Persistent state | ✅ DO | ❌ | ✅ | ❌ |
| Hibernation | ✅ | ❌ | N/A | N/A |
| CRDT support | ✅ Y.js | ❌ | ✅ | ❌ |
| Deploy command | npx partykit deploy |
Manual | Managed | Managed |
Y.js Integration (CRDT)
import { onConnect } from "y-partykit";
export default class SyncRoom implements Party.Server {
onConnect(conn: Party.Connection) {
// Automatic Y.js document syncing!
return onConnect(conn, this.room);
}
}
Deploy
npx partykit deploy
# Deployed to: https://my-app.username.partykit.dev
Resources
Building collaborative apps that need web data? My Apify tools extract data from any website — feed it into your PartyKit rooms for real-time collaborative analysis. Questions? Email spinov001@gmail.com
Top comments (0)