# クイックスタート

> 2 つのブラウザーで共同編集を試し、Client、Transport、Endpoint、Service、Adapter の最小構成をアプリケーションへ組み込みます。

- Human documentation: [https://docs.univer.ai/ja-JP/server/collaboration/quick-start](https://docs.univer.ai/ja-JP/server/collaboration/quick-start)

- Agent Markdown: [https://docs.univer.ai/ja-JP/server/collaboration/quick-start.md](https://docs.univer.ai/ja-JP/server/collaboration/quick-start.md)

- Requested language: `ja-JP`

- Content language: `ja-JP`

- Documentation version: `1.1.0`

- Source: [collaboration/quick-start.ja-JP.mdx](https://github.com/dream-num/documentation/blob/dev/content/server/collaboration/quick-start.ja-JP.mdx)

---

このページには 2 つの進め方があります。まず公式サンプルを動かし、2 つのブラウザーで共同編集の全経路を確認します。その後、最小の Server と Web の構成を読み、自分の Univer アプリケーションに取り込みます。

開始前に[環境とバージョンの要件](https://docs.univer.ai/ja-JP/server/requirements.md)を満たしてください。すべての `@univerjs/*` と `@univerjs-pro/*` を、対応する同一リリース群に固定する必要があります。

## 手順 1：公式サンプルを実行する

### 実行前の準備

リポジトリは **Node.js 24+** と **pnpm 10.32.1** を指定しています。`node --version` と `pnpm --version` を確認し、ロックファイルを保持してください。`pnpm example:*` はすべてリポジトリのルートで実行します。ブラウザーとサーバーのビルド、型検査、起動を行うコマンドであり、ホットリロードではありません。変更後は停止して再実行します。

クライアントライセンスがある場合、**ビルド前**にシェルで `UNIVER_LICENSE` を設定します。`vite.config.ts` がブラウザーバンドルに埋め込みます。ビルド済みサーバーの起動時だけ設定しても反映されません。[ライセンス設定](https://docs.univer.ai/ja-JP/server/license.md)を参照してください。

```bash
git clone https://github.com/dream-num/univer-collaboration-examples.git
cd univer-collaboration-examples
pnpm install --frozen-lockfile
pnpm example:quick-start
```

次を開きます。

```text
http://127.0.0.1:3010/?unit=quick-start-sheet
```

### リアルタイム共同編集の確認

1. 1 つ目のブラウザーウィンドウで URL 全体を開きます。
2. 別のブラウザープロファイルまたはプライベートウィンドウでも開きます。
3. どちらかの Sheet でセルを変更します。
4. 同じ編集がもう一方にも現れることを確認します。

サーバーが 2 つのオンライン Session を作るよう、独立したブラウザーコンテキストを使ってください。同じページ内の編集を見ただけでは Room、ACK、ブロードキャストの経路を検証できません。

### 成功によって確認できること

```text
Univer Collaboration Client
  → Node Transport
  → UniverCollabEndpoint
  → UniverCollabService
  → MemoryDatabaseAdapter
```

2 ブラウザーの同期は、HTTP で Unit を読み込み、使い捨ての Session Ticket で WebSocket Session を開き、同じ Room に参加したことを意味します。Service が OT を実行して新しいリビジョンを確定し、Adapter で保存して、Endpoint が他のメンバーへ配信します。

## 手順 2：アプリケーションに組み込む

以下は Server と Web の最小構成です。アプリケーション全体の構成は公式クイックスタートを参照してください。

* [server/main.ts](https://github.com/dream-num/univer-collaboration-examples/blob/main/examples/quick-start/server/main.ts)
* [web/main.ts](https://github.com/dream-num/univer-collaboration-examples/blob/main/examples/quick-start/web/main.ts)
* [package.json](https://github.com/dream-num/univer-collaboration-examples/blob/main/examples/quick-start/package.json)

既存の Univer Web アプリケーションでは Runtime、プリセット、UI を維持し、以下の Collaboration Client 設定と Server だけを追加します。空のプロジェクトでは、サンプルの `index.html`、`vite.config.ts`、スタイルをアプリケーションの枠としてコピーしてください。

### 実行可能なファイルから移行する

`examples/quick-start` をコピーし、`package.json`、`index.html`、`vite.config.ts`、`web/styles.css`、`web/main.ts`、`server/main.ts` を保持します。Express は作業ディレクトリから `dist/web` を読むため、サンプルディレクトリで build と start を実行します。Vite のライセンス定義と `#app` の高さも保持してください。以下のコードは構成の説明であり、完全なプロジェクトはこれらのファイルを起点にします。

サンプルのページと `/universer-api` は同一オリジンです。別のフロントエンドサーバーを使う場合、HTTP と WebSocket Upgrade をプロキシするか、クライアントの 5 つの URL をまとめて変更します。`unit` はサーバーが作成した ID と一致させます。URL パラメーターだけでは文書は作成されません。サンプルは URL 自動読み込みを無効にし、`unit` を読み取って `loadSheetAsync()` で明示的に読み込みます。アプリに組み込む際は[共同編集の統合](https://docs.univer.ai/ja-JP/server/collaboration/browser-integration.md)に従い、読み込む前に現在のユーザーを設定してください。

### 1. 対応する同一バージョンのパッケージ群をインストールする

サーバーには Transport、Endpoint、Service、Database Adapter が 1 つ必要です。ブラウザーには Collaboration Client が必要です。必要なパッケージを入れ、すべての Univer パッケージを同じ厳密なバージョンに固定します。

```bash
pnpm add \
  @univerjs-pro/collaboration@1.1.0 \
  @univerjs-pro/collaboration-client@1.1.0 \
  @univerjs-pro/collaboration-client-ui@1.1.0 \
  @univerjs-pro/collaboration-database-memory@1.1.0 \
  @univerjs-pro/collaboration-endpoint@1.1.0 \
  @univerjs-pro/collaboration-service@1.1.0 \
  @univerjs-pro/collaboration-transport-node@1.1.0 \
  @univerjs-pro/license@1.1.0 \
  @univerjs/core@1.1.0 \
  @univerjs/preset-sheets-core@1.1.0 \
  @univerjs/presets@1.1.0 \
  @univerjs/protocol@1.1.0 \
  express react react-dom rxjs
```

現在の構成と正確なバージョンは、実行可能な公式サンプルのマニフェストを基準にしてください。

### 2. Service、Endpoint、初期 Unit を作る

`UniverCollabService` は確定状態を管理する共同編集の中核です。Endpoint がブラウザーのプロトコルを Service に対応付け、Memory Adapter はスナップショット、変更セット、リビジョンを一時保存します。

```ts
import { createServer } from "node:http";
import express from "express";
import type { IWorkbookData } from "@univerjs/core";
import { LocaleType } from "@univerjs/core";
import { MemoryDatabaseAdapter } from "@univerjs-pro/collaboration-database-memory";
import { UniverCollabEndpoint } from "@univerjs-pro/collaboration-endpoint";
import { UniverCollabService } from "@univerjs-pro/collaboration-service";
import { createNodeTransport } from "@univerjs-pro/collaboration-transport-node";
import { ErrorCode, UniverType } from "@univerjs/protocol";

const UNIT_ID = "quick-start-sheet";
const unitData: IWorkbookData = {
  id: UNIT_ID,
  rev: 1,
  name: "Quick Start Sheet",
  appVersion: "",
  locale: LocaleType.EN_US,
  sheetOrder: ["sheet-1"],
  sheets: {
    "sheet-1": {
      id: "sheet-1",
      name: "Sheet 1",
      rowCount: 100,
      columnCount: 26,
      cellData: {},
    },
  },
  styles: {},
  resources: [],
};

const database = new MemoryDatabaseAdapter();
const service = new UniverCollabService({ dbAdapter: database });
const endpoint = new UniverCollabEndpoint(service);
const transport = createNodeTransport();

transport.use(async (context, next) => {
  context.userID = "demo-user";
  await next();
});
transport.register(endpoint);

await service.createUnitFromData(
  { type: UniverType.UNIVER_SHEET, data: unitData },
  { userID: "demo-user" },
);
```

固定の `demo-user` は、信頼できる ID が Transport から Endpoint と Service へ流れる仕組みの例です。本番では `transport.use()` で Cookie、Bearer トークン、セッションを検証してから、安定した業務用 `userID` を設定します。

### 3. 認可、HTTP、WebSocket の入口を配置する

現在の Collaboration Client は認可プロトコルを問い合わせます。クイックスタートはこのルートで常に `allowed: true` を返し、Transport をアプリケーションの HTTP サーバーに接続します。

```ts
const app = express();

app.post("/universer-api/authz/-/object/-/batch_allowed", express.json(), (request, response) => {
  const body = request.body as {
    requests: Array<{ unitID: string; objectID: string; actions: unknown[] }>;
  };
  response.json({
    error: { code: ErrorCode.OK, message: "" },
    objectActions: body.requests.map((item) => ({
      unitID: item.unitID,
      objectID: item.objectID,
      actions: item.actions.map((action) => ({ action, allowed: true })),
    })),
  });
});

app.use(express.static("dist/web"));

const server = createServer(app);
transport.attach(server);
server.listen(3010, "127.0.0.1");
```

全許可は学習用の簡略化で、セキュリティ境界ではありません。実際のアプリケーションでは HTTP 読み取り、リアルタイム JOIN、変更セット送信、Unit ライフサイクル操作を保護します。必要な範囲は [ID と認可](https://docs.univer.ai/ja-JP/server/collaboration/identity-and-authorization.md)を参照してください。

### 4. ブラウザー Runtime に Collaboration Client を登録する

通常の Web SDK とプリセットを維持し、共同編集プラグインとプロトコル URL を追加します。

```ts
import { LocaleType, LogLevel } from "@univerjs/core";
import { UniverCollaborationPlugin } from "@univerjs-pro/collaboration";
import { UniverCollaborationClientPlugin } from "@univerjs-pro/collaboration-client";
import CollaborationClientEnUS from "@univerjs-pro/collaboration-client/locale/en-US";
import {
  BrowserCollaborationSocketService,
  UniverCollaborationClientUIPlugin,
} from "@univerjs-pro/collaboration-client-ui";
import CollaborationClientUIEnUS from "@univerjs-pro/collaboration-client-ui/locale/en-US";
import { UniverLicensePlugin } from "@univerjs-pro/license";
import { UniverSheetsCorePreset } from "@univerjs/preset-sheets-core";
import UniverPresetSheetsCoreEnUS from "@univerjs/preset-sheets-core/locales/en-US";
import { createUniver, defaultTheme, mergeLocales } from "@univerjs/presets";
import "@univerjs-pro/collaboration-client/facade";
import "@univerjs/preset-sheets-core/lib/index.css";
import "@univerjs-pro/collaboration-client-ui/lib/index.css";

const httpProtocol = location.protocol === "https:" ? "https" : "http";
const wsProtocol = location.protocol === "https:" ? "wss" : "ws";
const baseURL = `${httpProtocol}://${location.host}/universer-api`;

const unitId = new URLSearchParams(location.search).get("unit");
if (!unitId) throw new Error("Open the URL printed by the server; it names the Sheet with ?unit=.");
const { univerAPI } = createUniver({
  locale: LocaleType.EN_US,
  locales: {
    [LocaleType.EN_US]: mergeLocales(
      UniverPresetSheetsCoreEnUS,
      CollaborationClientEnUS,
      CollaborationClientUIEnUS,
    ),
  },
  theme: defaultTheme,
  logLevel: LogLevel.WARN,
  collaboration: true,
  presets: [UniverSheetsCorePreset({ container: "app" })],
  plugins: [
    [UniverLicensePlugin, { license: import.meta.env.UNIVER_LICENSE || undefined }],
    UniverCollaborationPlugin,
    [
      UniverCollaborationClientPlugin,
      {
        socketService: BrowserCollaborationSocketService,
        sendChangesetTimeout: 200,
        authzUrl: `${baseURL}/authz`,
        snapshotServerUrl: `${baseURL}/snapshot`,
        collabSubmitChangesetUrl: `${baseURL}/comb`,
        collabWebSocketUrl: `${wsProtocol}://${location.host}/universer-api/comb/connect`,
        wsSessionTicketUrl: `${baseURL}/user/session-ticket`,
      },
    ],
    [UniverCollaborationClientUIPlugin, { enableUrlUnitLoader: false }],
  ],
});

const workbook = await univerAPI.getCollaboration().loadSheetAsync(unitId);
if (!workbook) throw new Error("Document could not be loaded");
```

ページには `id="app"` の要素が必要で、クエリパラメーターから Unit を選びます。

```text
/?unit=quick-start-sheet
```

### 5. 学習用の設定をアプリケーションの機能に置き換える

| 学習用設定           | 置き換えるもの                                  |
| --------------- | ---------------------------------------- |
| 固定の `demo-user` | アプリケーション認証 Middleware と安定したユーザー ID       |
| 常に許可する権限チェック    | 読み取り、JOIN、送信、ライフサイクルを覆うサーバー ACL          |
| 固定 Unit         | `createUnitFromData()` を呼ぶ作成 API と製品レコード |
| Memory Adapter  | SQLite または契約テスト済みの独自永続化 Adapter          |

次に[データベースアダプター](https://docs.univer.ai/ja-JP/server/collaboration/database-adapters.md)と [ID・認可](https://docs.univer.ai/ja-JP/server/collaboration/identity-and-authorization.md)を実装し、必要に応じて [History、Thread Comment、Worktree、Exchange](https://docs.univer.ai/ja-JP/server/collaboration/extensions.md) を追加します。実行できる構成は[サンプル一覧](https://docs.univer.ai/ja-JP/server/collaboration/examples.md)を参照してください。

## 初回実行のトラブルシューティング

| 症状           | 確認点                                                                                    |
| ------------ | -------------------------------------------------------------------------------------- |
| インストール・ビルド失敗 | Node.js 24+、指定 pnpm、Univer のバージョン統一                                                    |
| 3010 が使用中    | 前のサンプルを停止、または `PORT=3011` を設定して両ブラウザーの URL を変更                                         |
| 白画面・静的ファイル不足 | ビルド完了、サンプルディレクトリで起動、`#app` の高さ                                                         |
| 編集が同期しない     | 完全な URL が同じ、snapshot と session-ticket が成功、`/universer-api/comb/connect` の WebSocket 接続 |
| 再起動で消える      | Quick Start はメモリ保存。SQLite サンプルへ進む                                                      |
