mcpField
Y
yjs-nextjs

yjs-nextjs

github.com/pproenca開発21861 回インストール11 週間前に更新
リポジトリ

yjs-nextjs について

yjs-nextjs は、Next.js 16 App Router で Yjs による共同編集を実装するためのコーディングリファレンススキルです。Yjs 13.6.31 を対象に、同期、永続化、React 連携や、同時編集で見落としやすいデータ損失の問題を扱います。

主な機能

  1. 01同期構成と依存関係の選定
  2. 02バイナリ更新の転送と永続化
  3. 03共有型によるデータモデリング
  4. 04React のドキュメントライフサイクルと連携
  5. 05Undo、オフライン読み込み、カーソル
  6. 06Tiptap とフォームの連携

活用シーン

  1. 01Next.js アプリに共同編集やオフライン同期を追加
  2. 02同時編集による内容の消失や重複を調査
  3. 03Y.Doc の永続化と更新の圧縮を設計
  4. 04React での Yjs Provider のライフサイクルを確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/pproenca/dot-skills --skill yjs-nextjs

インストール後、Claude Code で/yjs-nextjsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

AGENTS.md
metadata.json
assets/templates/
_template.md
references/
_sections.md
hist-scope-undo-by-origin.md
hist-snapshots-require-gc-disabled.md
hist-wait-for-indexeddb-sync.md
host-authorize-rooms-not-updates.md
host-pin-the-yjs-13-track.md
host-route-handlers-cannot-upgrade.md
host-trpc-is-not-the-sync-channel.md
host-vercel-lacks-instance-affinity.md
host-websocket-server-is-not-production.md
model-nested-types-not-plain-objects.md
model-seed-the-document-once.md
model-yarray-has-no-move.md
model-ytext-only-for-prose.md
pres-awareness-is-ephemeral.md
pres-relative-positions-for-cursors.md
react-keep-yjs-client-only.md
react-stable-doc-and-provider.md
react-subscribe-via-usesyncexternalstore.md
ui-do-not-drive-inputs-from-the-doc.md
ui-tiptap-collaboration-wiring.md
wire-base64-not-superjson.md
wire-compaction-needs-a-doc-roundtrip.md
wire-rehydrate-to-uint8array.md
wire-send-updates-not-state.md

詳細

Next.js 16、tRPC、shadcn/ui での Yjs

App Router のコードベースで使う Yjs 13.6.31 について、共同編集で必要となる判断とその解決方法を、エージェントがコードの作成やレビュー時に適用できるようにまとめています。各ルールでは、誤ったデフォルトを明示して修正します。モデルがすでに正しく処理できることに関するルールはありません。

こうした問題の大半は、気づかないうちに発生します。Yjs の収束性は保たれ、エディターも動作し続けるため、データ損失が「変更が元に戻った」という形で後から表面化します。そのため、以下のルールでは、失敗を示す証拠を先に取り上げています。その多くは、根拠なく断言するのではなく、Yjs 13.6.31 を使って直接測定したものです。

適用する場面

  • Next.js 16 の App Router アプリに、共同編集、プレゼンス、オフライン同期を実装する場合
  • ドキュメントモデルの共有型を選択する場合や、並行編集時に編集内容が失われるモデルをレビューする場合
  • 同期バックエンドの実行場所を決める場合や、Yjs プロバイダーと並行して tRPC プロシージャを接続する場合
  • Y.Doc の状態をデータベースに永続化する場合や、保存済みの更新を圧縮する場合
  • Yjs ドキュメントを React にバインドする場合(プロバイダーのライフサイクル、サブスクリプション、Strict Mode、SSR)
  • Tiptap や shadcn/ui のフォームコントロールをライブドキュメントに接続する場合
  • 同期はするものの、コンテンツが重複したり、空になったり、元に戻ったりするドキュメントをデバッグする場合

このスキルでは、Next.js App Router の一般的なパターン(nextjs スキルを使用)、tRPC の一般的な使い方(trpc)、shadcn/ui のコンポーネント規約(shadcn)は扱いません。CRDT と交差する部分のみを扱います。

バージョン固定

ルールは、y-websocket 3.0.0、y-protocols 1.0.7、y-indexeddb 9.0.12 と組み合わせた Yjs 13.6.31 を対象としています。Yjs は @y/* スコープで v14 への移行中であり、複数のパッケージがすでに latest または main をそのプレリリース系列に移行しています。@y/[email protected] は yjs@^14.0.0-7 に依存しています。何かをインストールする前に、host-pin-the-yjs-13-track を参照してください。

ルールのカテゴリ

#カテゴリプレフィックス対象
1同期トポロジーと依存関係host-同期ループの実行場所、構築するバックエンド、信頼境界の位置、v13 系列のバージョン
2バイナリ転送と永続化wire-Uint8Array の更新を JSON 境界越しに移動し、ストレージに保存する方法
3共有型での状態モデリングmodel-フィールドごとに使う共有型。並行編集のマージと相互破壊を左右します
4ドキュメントのライフサイクルと React バインディングreact-レンダリングをまたいだ単一ドキュメント、Strict Mode、サブスクリプション、サーバー境界
5Undo、スナップショット、オフライン読み込みhist-オリジン単位の履歴、ガベージコレクション、読み込み順序
6アウェアネスとカーソルpres-一時的なプレゼンスと、並行編集後も維持される位置
7エディターとフォームの統合ui-ライブドキュメントを使った Tiptap と shadcn/ui のフォームコントロール

クイックリファレンス

1. 同期トポロジーと依存関係
  • host-route-handlers-cannot-upgrade — App Router にはソケットをアップグレードする API がありません。同期サーバーはリクエストとは独立して稼働する必要があります
  • host-vercel-lacks-instance-affinity — Vercel は WebSocket を提供しますが、ルームを特定のインスタンスに固定しません。インメモリレジストリでは、1つのドキュメントが2つに分裂します
  • host-websocket-server-is-not-production — リファレンスサーバーは出発点にすぎず、YPERSISTENCE はすでに存在しません
  • host-pin-the-yjs-13-track — latest をインストールすると、v13 アプリに Yjs 14 のプレリリースが取り込まれます
  • host-trpc-is-not-the-sync-channel — SSE は一方向で、バイナリ入力は POST のみです。認可とスナップショットには tRPC を使用してください
  • host-authorize-rooms-not-updates — CRDT の更新はスキーマ検証も権限チェックもできないため、ルームが信頼境界になります
2. バイナリの転送と永続化
3. 共有型での状態のモデル化
  • model-nested-types-not-plain-objects — Y.Map 内のプレーンオブジェクトは 1 つの競合単位となるため、異なるフィールドへの同時編集では片方が失われます
  • model-yarray-has-no-move — 2 人が同時に行をドラッグすると、削除してから挿入する方法では行が重複します
  • model-ytext-only-for-prose — 2 人が Y.Text のタイトルをそれぞれ入力し直すと、両方の値がつなぎ合わされます
  • model-seed-the-document-once — 空かどうかのチェックはすべてのクライアントで通るため、テンプレートが 2 回挿入されます
4. ドキュメントのライフサイクルと React バインディング
  • react-stable-doc-and-provider — Strict Mode ではセットアップ、クリーンアップ、セットアップの順に実行されるため、1 つのエフェクト内で作成と破棄を管理します
  • react-subscribe-via-usesyncexternalstore — 公式のバインディングは存在せず、toJSON() は呼び出すたびに新しい参照を返します
  • react-keep-yjs-client-only — プロバイダーにはブラウザーのグローバル変数が必要であり、'use client' を指定してもサーバー上でレンダリングされます
5. 元に戻す、スナップショット、オフライン読み込み
  • hist-scope-undo-by-origin — デフォルトの元に戻すマネージャーはリモート編集も追跡するため、同僚の作業を元に戻してしまいます
  • hist-snapshots-require-gc-disabled — これは構築時に決まります。そうでない場合、スナップショットの復元時にエラーが発生します
  • hist-wait-for-indexeddb-sync — 読み込み前のドキュメントと空のドキュメントは区別できません
6. アウェアネスとカーソル
  • pres-awareness-is-ephemeral — ドキュメント内のプレゼンスは永続的で、バージョン管理され、クリーンアップされません
  • pres-relative-positions-for-cursors — 誰かがその位置より前に入力した時点で、インデックスは同じ場所を示さなくなります
7. エディターとフォームの統合

使い方

判断が必要になったら、該当するリファレンスファイルを読みます。各ルールでは、修正対象となる誤ったデフォルトを示したうえで、標準的な方法を説明します。誤った方法が実際に陥りやすい落とし穴である場合は、誤りと正しい方法を対比しています。

コードを書くのではなくデバッグする場合は、症状から始めます。

症状最初に読むもの
ドキュメントが空白で読み込まれるwire-rehydrate-to-uint8array、hist-wait-for-indexeddb-sync
コンテンツが二重に表示されるmodel-seed-the-document-once、ui-tiptap-collaboration-wiring
誰かの編集内容が通知なく元に戻るmodel-nested-types-not-plain-objects、hist-scope-undo-by-origin
リスト項目をドラッグすると重複するmodel-yarray-has-no-move
2つのエディターがお互いを認識しないhost-vercel-lacks-instance-affinity
ユーザーが編集できるはずのないフィールドを編集したhost-authorize-rooms-not-updates
共同編集者が退出した後もアバターが残るpres-awareness-is-ephemeral
入力中にキャレットが末尾へ飛ぶui-do-not-drive-inputs-from-the-doc
無限レンダリングループまたはスナップショットエラーが発生するreact-subscribe-via-usesyncexternalstore
本番環境では動くが、開発環境では動かないreact-stable-doc-and-provider

リファレンスファイル

ファイル説明
references/_sections.mdカテゴリーの定義と順序
assets/templates/_template.md新しいルール用のテンプレート
AGENTS.mdすべてのルールをまとめた自動生成の目次
metadata.jsonバージョンとソースの参照情報

関連スキル

  • nextjs — CRDT レイヤー外での App Router のキャッシュ、Server Components、ルーティング
  • trpc — tRPC v11 のルーター、リンク、サブスクリプションに関するルール一式
  • shadcn — このスキルが基盤とするコンポーネントの組み合わせ方とフォームのパターン
  • zod — ここで紹介する tRPC プロシージャの例で使用するバリデーター

コメント