Writing Skills
writing-skills
效率与协作技能,来自 obra/superpowers,查看原文获取完整用途和操作说明。
partykit【部署与运维】Build multiplayer and collaborative apps with PartyKit. Use when a user asks to build real-time collaboration features, create multiplayer experiences, add live cursors, build collaborative editing, create real-time voting or polls, sync state across clients, or build WebSocket servers on the edge. Covers PartyServer definition, client connections, s…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
PartyKit is a platform for building real-time, multiplayer, and collaborative applications. Each "party" is an isolated room running on Cloudflare's edge network — close to users for low latency. Unlike Socket.IO (which needs a persistent server), PartyKit runs serverless with automatic hibernation — you pay for active connections, not idle servers. Use it for collaborative editing, live cursors, multiplayer games, real-time polls, and any feature where multiple clients need synchronized state.
# Create new project
npm create partykit@latest my-party
cd my-party
# Or add to existing project
npm install partykit partysocket
# Start development server
npx partykit dev
# Server running at http://127.0.0.1:1999
// party/index.ts — A PartyKit server (one instance per room)
import type * as Party from 'partykit/server'
export default class ChatRoom implements Party.Server {
// Shared state for this room
messages: Array<{ author: string; text: string; timestamp: number }> = []
constructor(readonly room: Party.Room) {}
onConnect(conn: Party.Connection, ctx: Party.ConnectionContext) {
/** Called when a client connects to this room. */
// Send existing messages to the new connection
conn.send(JSON.stringify({ type: 'history', messages: this.messages }))
// Notify others
this.room.broadcast(
JSON.stringify({ type: 'user-joined', connectionId: conn.id }),
[conn.id] // exclude the new connection
)
}
onMessage(message: string, sender: Party.Connection) {
/** Called when a client sends a message. */
const data = JSON.parse(message)
if (data.type === 'chat') {
const chatMessage = {
author: data.author,
text: data.text,
timestamp: Date.now(),
}
this.messages.push(chatMessage)
// Broadcast to all connections in this room
this.room.broadcast(JSON.stringify({ type: 'new-message', message: chatMessage }))
}
}
onClose(conn: Party.Connection) {
this.room.broadcast(JSON.stringify({ type: 'user-left', connectionId: conn.id }))
}
}
// hooks/useParty.ts — React hook for PartyKit connection
import usePartySocket from 'partysocket/react'
export function useChatRoom(roomId: string, userName: string) {
const [messages, setMessages] = useState<ChatMessage[]>([])
const socket = usePartySocket({
host: process.env.NEXT_PUBLIC_PARTYKIT_HOST!,
room: roomId,
onMessage(event) {
const data = JSON.parse(event.data)
if (data.type === 'history') {
setMessages(data.messages)
} else if (data.type === 'new-message') {
setMessages(prev => [...prev, data.message])
}
},
})
const sendMessage = (text: string) => {
socket.send(JSON.stringify({ type: 'chat', author: userName, text }))
}
return { messages, sendMessage, readyState: socket.readyState }
}
// party/cursors.ts — Real-time cursor sharing (like Figma)
import type * as Party from 'partykit/server'
type Cursor = { x: number; y: number; name: string; color: string }
export default class CursorRoom implements Party.Server {
cursors = new Map<string, Cursor>()
constructor(readonly room: Party.Room) {}
onMessage(message: string, sender: Party.Connection) {
const cursor: Cursor = JSON.parse(message)
this.cursors.set(sender.id, cursor)
// Broadcast cursor position to everyone else
this.room.broadcast(
JSON.stringify({ id: sender.id, ...cursor }),
[sender.id]
)
}
onClose(conn: Party.Connection) {
this.cursors.delete(conn.id)
this.room.broadcast(JSON.stringify({ id: conn.id, gone: true }))
}
}
# Deploy to Cloudflare's edge network
npx partykit deploy
# Custom domain
npx partykit deploy --domain my-party.example.com
# Environment variables
npx partykit env add OPENAI_API_KEY
User prompt: "Add real-time collaboration to our note-taking app — multiple users editing the same document with live cursors."
The agent will:
User prompt: "Add real-time polls to our presentation tool. Audience votes on their phones, results update live on the presenter's screen."
The agent will:
this.room.storage) or an external database.partysocket (not raw WebSocket) on the client — it handles reconnection, buffering, and the PartyKit protocol.