jpskill.com
🛠️ 開発・MCP コミュニティ

partykit

PartyKitは、リアルタイムな共同作業機能や多人数参加型体験を構築したい場合に、クライアント間の状態同期、WebSocketサーバー構築などをエッジ環境で実現するのに役立つSkill。

📜 元の英語説明(参考)

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, state management, hibernation, and deployment to Cloudflare.

🇯🇵 日本人クリエイター向け解説

一言でいうと

PartyKitは、リアルタイムな共同作業機能や多人数参加型体験を構築したい場合に、クライアント間の状態同期、WebSocketサーバー構築などをエッジ環境で実現するのに役立つSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o partykit.zip https://jpskill.com/download/15234.zip && unzip -o partykit.zip && rm partykit.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/15234.zip -OutFile "$d\partykit.zip"; Expand-Archive "$d\partykit.zip" -DestinationPath $d -Force; ri "$d\partykit.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して partykit.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → partykit フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

PartyKit

概要

PartyKit は、リアルタイム、マルチプレイヤー、およびコラボレーションアプリケーションを構築するためのプラットフォームです。各「party」は、Cloudflare のエッジネットワーク上で実行される隔離されたルームであり、低レイテンシのためにユーザーの近くに配置されます。Socket.IO (永続的なサーバーが必要) とは異なり、PartyKit は自動ハイバネーションでサーバーレスで実行されます。アクティブな接続に対してのみ料金が発生し、アイドル状態のサーバーには料金は発生しません。共同編集、ライブカーソル、マルチプレイヤーゲーム、リアルタイム投票、および複数のクライアントが状態を同期する必要があるあらゆる機能に使用できます。

手順

ステップ 1: セットアップ

# 新しいプロジェクトを作成
npm create partykit@latest my-party
cd my-party

# または既存のプロジェクトに追加
npm install partykit partysocket

# 開発サーバーを起動
npx partykit dev
# Server running at http://127.0.0.1:1999

ステップ 2: Party サーバーの定義

// party/index.ts — PartyKit サーバー (ルームごとに 1 つのインスタンス)
import type * as Party from 'partykit/server'

export default class ChatRoom implements Party.Server {
  // このルームの共有状態
  messages: Array<{ author: string; text: string; timestamp: number }> = []

  constructor(readonly room: Party.Room) {}

  onConnect(conn: Party.Connection, ctx: Party.ConnectionContext) {
    /** クライアントがこのルームに接続したときに呼び出されます。 */
    // 既存のメッセージを新しい接続に送信
    conn.send(JSON.stringify({ type: 'history', messages: this.messages }))

    // 他のユーザーに通知
    this.room.broadcast(
      JSON.stringify({ type: 'user-joined', connectionId: conn.id }),
      [conn.id]    // 新しい接続を除外
    )
  }

  onMessage(message: string, sender: Party.Connection) {
    /** クライアントがメッセージを送信したときに呼び出されます。 */
    const data = JSON.parse(message)

    if (data.type === 'chat') {
      const chatMessage = {
        author: data.author,
        text: data.text,
        timestamp: Date.now(),
      }
      this.messages.push(chatMessage)

      // このルームのすべての接続にブロードキャスト
      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 }))
  }
}

ステップ 3: クライアント接続

// hooks/useParty.ts — PartyKit 接続用の React フック
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 }
}

ステップ 4: ライブカーソル

// party/cursors.ts — リアルタイムカーソル共有 (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)

    // カーソルの位置を他の全員にブロードキャスト
    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 }))
  }
}

ステップ 5: デプロイ

# Cloudflare のエッジネットワークにデプロイ
npx partykit deploy

# カスタムドメイン
npx partykit deploy --domain my-party.example.com

# 環境変数
npx partykit env add OPENAI_API_KEY

例 1: ドキュメントアプリへの共同編集機能の追加

ユーザープロンプト: 「リアルタイムのコラボレーションをメモアプリに追加します。複数のユーザーが同じドキュメントをライブカーソルで編集します。」

エージェントは以下を行います。

  1. ドキュメントの状態とカーソルの位置を管理する PartyKit サーバーを作成します。
  2. コンフリクトフリーな同時編集のために CRDT (Yjs) を使用します。
  3. 各エディターの位置と名前を示すカーソルのプレゼンスを追加します。
  4. グローバルな低レイテンシアクセスのために Cloudflare のエッジにデプロイします。

例 2: ライブ投票/投票機能の構築

ユーザープロンプト: 「プレゼンテーションツールにリアルタイム投票を追加します。聴衆は携帯電話で投票し、結果はプレゼンターの画面でライブで更新されます。」

エージェントは以下を行います。

  1. 投票状態を持つ投票ごとに party ルームを作成します。
  2. 聴衆は携帯電話経由で接続し、投票します。
  3. プレゼンタービューは、リアルタイムの投票数更新を受信します。
  4. 投票が入ると結果がアニメーション化されます。

ガイドライン

  • 各ルームは隔離されたインスタンスです。状態はルーム間で共有されません。ルーム ID を使用してデータをパーティション分割します (ドキュメントごと、ゲームセッションごと、チャットチャネルごとに 1 つのルーム)。
  • PartyKit はアクティブな接続がないルームを休止状態にします。アイドル状態のルームに対して料金は発生しません。接続が存在する間、状態はルームオブジェクトに保持されます。
  • 永続的な状態 (ルームの休止状態からの復帰) の場合は、PartyKit の組み込みストレージ (this.room.storage) または外部データベースを使用します。
  • クライアントでは partysocket (生の WebSocket ではない) を使用します。これは、再接続、バッファリング、および PartyKit プロトコルを処理します。
  • PartyKit は Cloudflare のエッジネットワークにデプロイされます。ルームは最初に接続したユーザーに最も近い場所で実行され、その後、後続のすべてのユーザーがその場所に接続します。
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

PartyKit

Overview

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.

Instructions

Step 1: Setup

# 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

Step 2: Define a Party Server

// 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 }))
  }
}

Step 3: Client Connection

// 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 }
}

Step 4: Live Cursors

// 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 }))
  }
}

Step 5: Deploy

# 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

Examples

Example 1: Add collaborative editing to a document app

User prompt: "Add real-time collaboration to our note-taking app — multiple users editing the same document with live cursors."

The agent will:

  1. Create a PartyKit server that manages document state and cursor positions.
  2. Use CRDT (Yjs) for conflict-free concurrent editing.
  3. Add cursor presence showing each editor's position and name.
  4. Deploy to Cloudflare's edge for global low-latency access.

Example 2: Build a live polling/voting feature

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:

  1. Create a party room per poll with vote state.
  2. Audience connects via phone, casts votes.
  3. Presenter view receives real-time vote count updates.
  4. Results animate as votes come in.

Guidelines

  • Each room is an isolated instance — state is not shared between rooms. Use room IDs to partition data (one room per document, per game session, per chat channel).
  • PartyKit hibernates rooms with no active connections — you're not paying for idle rooms. State persists in the room object while connections exist.
  • For persistent state (survive room hibernation), use PartyKit's built-in storage (this.room.storage) or an external database.
  • Use partysocket (not raw WebSocket) on the client — it handles reconnection, buffering, and the PartyKit protocol.
  • PartyKit deploys to Cloudflare's edge network — rooms run closest to the first connecting user, then all subsequent users connect to that location.