「コラボレーションドキュメント編集アプリを作りたい」
Google Docsのように複数人でリアルタイム編集できて、AIが@aiでディスカッションに参加する。そんなアプリを構想したときの技術選定の記録。
リアルタイム同期の選択肢
Liveblocks
Liveblocksはリアルタイムコラボレーション機能を提供するインフラサービス。CloudflareのDurable ObjectsとWebSocketを使って「ルーム」を構築している。
// Liveblocksの基本的な使い方
import { createClient } from "@liveblocks/client";
const client = createClient({
publicApiKey: "pk_xxx",
});
// ルームに接続
const { room } = client.enterRoom("my-document", {
initialPresence: { cursor: null },
});
特徴:
- ライブカーソルが60fpsで動作するほど低レイテンシー
- Presence機能(誰がオンラインで、どこを編集しているか)
- Comments、AI Copilot機能が組み込み
- BlockNote、Tiptapとの公式統合パッケージあり
Yjs
オープンソースのCRDT(Conflict-free Replicated Data Type)ライブラリ。Notion、Figmaなど大規模プロダクトでの実績がある。
import * as Y from 'yjs';
import { WebsocketProvider } from 'y-websocket';
const ydoc = new Y.Doc();
const provider = new WebsocketProvider('wss://my-server.com', 'room-id', ydoc);
// ドキュメントの変更を監視
ydoc.on('update', () => {
console.log('Document updated');
});
特徴:
- オープンソースで自由度が高い
- オフライン編集対応(再接続時に自動同期)
- 自前でWebSocketサーバーを建てる必要がある
比較
| 観点 | Liveblocks | Yjs |
|---|---|---|
| 導入コスト | 低(SaaS) | 中(サーバー構築必要) |
| 月額費用 | あり | インフラ費用のみ |
| カスタマイズ性 | 中 | 高 |
| オフライン対応 | △ | ◎ |
| 学習コスト | 低 | 中 |
結論: 早く始めたいならLiveblocks、自由度が必要ならYjs。
エディタの選択
リアルタイム同期と組み合わせるエディタ。
Tiptap
ProseMirrorベースのヘッドレスエディタ。
import { useEditor, EditorContent } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import Collaboration from '@tiptap/extension-collaboration';
import * as Y from 'yjs';
const ydoc = new Y.Doc();
const editor = useEditor({
extensions: [
StarterKit,
Collaboration.configure({
document: ydoc,
}),
],
});
特徴:
- 拡張性が高い(メンション、コメントなど追加可能)
- Liveblocks、Yjsとの統合がスムーズ
- TypeScriptサポートが良好
BlockNote
Notionライクなブロックエディタ。
import { useBlockNote } from "@blocknote/react";
import { BlockNoteView } from "@blocknote/mantine";
const editor = useBlockNote({
collaboration: {
provider: liveblocksProvider,
fragment: ydoc.getXmlFragment("document"),
user: { name: "User", color: "#ff0000" },
},
});
特徴:
- Notionに慣れたユーザーに馴染みやすいUI
- スラッシュコマンド、ドラッグ&ドロップが標準
- ブロック単位の操作に特化
選択のポイント
- Tiptap: カスタマイズ重視、細かい制御が必要
- BlockNote: Notionライクな体験を早く実現したい
AIインテグレーション
@aiでAIを呼び出してテキスト生成するイメージ。
アーキテクチャ
ユーザーが@aiを入力
↓
メンションをトリガーとして検出
↓
Claude API呼び出し(ストリーミング)
↓
生成結果をエディタに挿入
実装イメージ
// Tiptapでメンション拡張を作成
import { Extension } from '@tiptap/core';
import Mention from '@tiptap/extension-mention';
const AIMention = Mention.configure({
HTMLAttributes: { class: 'ai-mention' },
suggestion: {
items: ({ query }) => {
if (query.toLowerCase() === 'ai') {
return [{ id: 'ai', label: 'AI Assistant' }];
}
return [];
},
command: ({ editor, range, props }) => {
// @aiが確定されたらAPIを呼び出す
handleAIMention(editor, range);
},
},
});
async function handleAIMention(editor, range) {
const context = getDocumentContext(editor);
const response = await fetch('/api/ai/generate', {
method: 'POST',
body: JSON.stringify({ context, prompt: '...' }),
});
// ストリーミングで結果を挿入
const reader = response.body.getReader();
// ...
}
注意点
「AIとディスカッション」ではなく「AIを文書生成ツールとして使う」
当初は「AIがディスカッションに参加する」イメージだったが、考え直した。
- 人間同士がリアルタイムで共同編集・議論
@aiでAIを呼び出してテキスト生成(要約、下書き、リライト)- 生成結果をそのまま文書に挿入
AIはあくまでツール。議論自体は人間同士で行う。
ドキュメント同期の課題:Git連携
「PM/ディレクターがドキュメントを編集して、それが開発リポジトリと同期される」
これが意外と難しい。
Google Docs ↔ Git
Google DocsからGitリポジトリへの一方向同期は可能。
import { google } from 'googleapis';
const drive = google.drive({ version: 'v3', auth });
async function exportAsMarkdown(fileId: string): Promise<string> {
// HTMLとしてエクスポート
const res = await drive.files.export({
fileId,
mimeType: 'text/html',
});
// HTMLをMarkdownに変換
const markdown = turndownService.turndown(res.data);
return markdown;
}
問題: 双方向同期が実質不可能。Google Docs APIでの書き込みは「全置換」になり、差分マージができない。
Notion ↔ Git
Notionは読み書き両方のAPIがある。
import { Client } from '@notionhq/client';
import { NotionToMarkdown } from 'notion-to-md';
import { markdownToBlocks } from '@tryfabric/martian';
// Notion → Markdown
const n2m = new NotionToMarkdown({ notionClient: notion });
const mdBlocks = await n2m.pageToMarkdown(pageId);
const markdown = n2m.toMarkdownString(mdBlocks).parent;
// Markdown → Notion
const blocks = markdownToBlocks(markdown);
await notion.blocks.children.append({
block_id: pageId,
children: blocks,
});
問題: コンフリクト解決は自前実装が必要。画像URLの期限切れ対策も必要。
GitBook
Git連携がネイティブ。設定だけで双方向同期が動く。
# .gitbook.yaml
root: ./docs/
structure:
readme: README.md
summary: SUMMARY.md
PM/ディレクター: GitBookのWeb UIで編集 → 自動でGitHubにcommit
開発者: ローカルでMarkdown編集 → push → 自動でGitBookに反映
コンフリクト: Gitの仕組みで処理される(通常のGitコンフリクト)。
比較まとめ
| ツール | リポジトリ → ツール | ツール → リポジトリ | 双方向 |
|---|---|---|---|
| Google Docs | △ 大変 | ◎ | 実質無理 |
| Notion | ○ 可能 | ◎ | ○ |
| GitBook | ◎ | ◎ | ◎ ネイティブ |
サービスとしての差別化
「これ、Notionでいいんじゃない?」
その通り。差別化がないとNotionに勝てない。
ニッチ特化の方向性
技術系
- API仕様書 + 実際のエンドポイントテスト連動
- インシデント対応のRunbook(Slack/PagerDuty連携)
業務特化
- 契約書レビュー(変更履歴 + AI差分チェック)
- 議事録 → タスク自動抽出 → Jira/Linear連携
クリエイティブ系
- シナリオ/脚本執筆(キャラ設定AIが一貫性チェック)
- 翻訳ワークフロー(原文と訳文並べて複数人でレビュー)
規制/コンプライアンス系
- 監査証跡が必要なドキュメント
- 医療/法務で「誰がいつ何を編集したか」厳密に残す
推奨スタック
MVP(3〜4ヶ月)を目指すなら:
const stack = {
frontend: {
framework: "Next.js 14 (App Router)",
editor: "Tiptap or BlockNote",
realtime: "Liveblocks (SaaS)",
styling: "Tailwind CSS",
},
backend: {
ai: "Claude API (ストリーミング)",
auth: "Clerk or Supabase Auth",
database: "PostgreSQL (Supabase)",
},
};
まとめ
リアルタイムコラボ文書編集は、技術的には十分実現可能になっている。Liveblocks + Tiptap/BlockNoteの組み合わせで、Google Docsライクな体験は比較的早く作れる。
難しいのは「Notionでいいじゃん」を乗り越える差別化。ニッチに振り切って、特定領域の深い課題を解決するアプローチが現実的だ。
Git連携については、双方向同期を本気でやるならGitBookが最も楽。Notionは自前実装すればできるが、コンフリクト解決の設計が必要。Google Docsは一方向に割り切るのが吉。