# Inicio rápido

> Ejecuta colaboración en dos navegadores e integra la composición mínima de Client, Transport, Endpoint, Service y Adapter en tu aplicación.

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

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

- Requested language: `es-ES`

- Content language: `es-ES`

- Documentation version: `1.2.0`

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

---

Esta página propone dos caminos. Primero ejecuta el ejemplo oficial y verifica el recorrido completo en dos navegadores. Después lee y copia la composición mínima de Server y Web en tu propia aplicación Univer.

Antes de empezar, cumple los [requisitos de entorno y versión](https://docs.univer.ai/es-ES/server/requirements.md). Todos los paquetes `@univerjs/*` y `@univerjs-pro/*` deben fijarse al mismo conjunto de versiones compatibles.

## Camino uno: ejecutar el ejemplo oficial

### Preparar el primer inicio

El repositorio requiere **Node.js 24+** y declara **pnpm 10.32.1**. Comprueba `node --version` y `pnpm --version` y conserva el lockfile. Ejecuta todos los comandos `pnpm example:*` desde la raíz. Compilan navegador y servidor, verifican tipos y arrancan el servicio; no ofrecen recarga en caliente. Tras editar el código, detén el proceso y repite el comando.

Si tienes licencia de cliente, define `UNIVER_LICENSE` en el shell **antes de compilar**. `vite.config.ts` la incorpora al bundle del navegador. Definirla solo al arrancar un servidor ya compilado no actualiza el cliente. Consulta la [configuración de licencia](https://docs.univer.ai/es-ES/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
```

Abre:

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

### Verificar la colaboración en tiempo real

1. Abre la URL completa en una ventana del navegador.
2. Ábrela de nuevo en otro perfil o ventana privada.
3. Cambia una celda en cualquiera de las hojas.
4. Confirma que el cambio aparece en el otro navegador.

Usa dos contextos independientes para que el servidor cree dos Sessions en línea. Observar una edición en la misma página no verifica el recorrido de Room, ACK y difusión.

### Qué demuestra el resultado

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

La sincronización indica que los navegadores cargaron una Unit por HTTP, abrieron Sessions WebSocket mediante un Session Ticket de un solo uso y se unieron a la misma Room. El Service realizó OT, confirmó una revisión nueva, la guardó mediante el Adapter y el Endpoint la difundió al resto.

## Camino dos: integrarlo en tu aplicación

El código siguiente muestra la composición mínima de Server y Web. El inicio rápido oficial proporciona la estructura completa de la aplicación:

* [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)

Si ya tienes una aplicación Univer Web, conserva Runtime, presets y UI y añade solo la configuración del cliente Collaboration y el servidor siguientes. En un proyecto vacío, copia `index.html`, `vite.config.ts` y los estilos del ejemplo como estructura de la aplicación.

### Migrar desde los archivos ejecutables

Copia `examples/quick-start` conservando `package.json`, `index.html`, `vite.config.ts`, `web/styles.css`, `web/main.ts` y `server/main.ts`. Ejecuta build y start desde ese directorio: Express lee `dist/web` respecto al directorio actual. Mantén la definición de licencia de Vite y una altura distinta de cero en `#app`. El código siguiente explica el montaje; estos archivos son el proyecto ejecutable completo.

La página y `/universer-api` comparten origen. Si separas el frontend, configura el proxy para HTTP y WebSocket Upgrade o cambia juntas las cinco URL del cliente. `unit` debe coincidir con el ID creado en el backend. El parámetro URL no crea documentos. El ejemplo lee `unit` y carga explícitamente con `loadSheetAsync()`; en tu aplicación, establece el usuario actual antes de cargar, como se describe en [Integración de colaboración](https://docs.univer.ai/es-ES/server/collaboration/browser-integration.md).

### 1. Instalar un conjunto de versiones compatibles

El servidor necesita Transport, Endpoint, Service y un Database Adapter. El navegador necesita el cliente Collaboration. Instala los paquetes necesarios y fija todos los paquetes Univer a la misma versión exacta:

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

El manifiesto del ejemplo oficial ejecutable es la referencia para la composición actual y las versiones exactas.

### 2. Crear Service, Endpoint y Unit inicial

`UniverCollabService` es el núcleo autoritativo de colaboración. El Endpoint conecta el protocolo del navegador con el Service, mientras que Memory Adapter guarda temporalmente instantáneas, conjuntos de cambios y revisiones:

```ts
import type { IWorkbookData } from "@univerjs/core";
import { createServer } from "node:http";
import express from "express";
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" },
);
```

El `demo-user` fijo muestra cómo la identidad de confianza pasa de Transport a Endpoint y Service. En producción, valida tu cookie, token Bearer o sesión en `transport.use()` antes de establecer un `userID` de negocio estable.

### 3. Montar autorización y puntos de entrada HTTP y WebSocket

El cliente Collaboration actual consulta un protocolo de autorización. El inicio rápido devuelve siempre `allowed: true` para esa ruta y conecta Transport al servidor HTTP de la aplicación:

```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");
```

Permitir todo es una simplificación didáctica, no un límite de seguridad. Una aplicación real debe proteger lecturas HTTP, JOIN en tiempo real, envío de cambios y operaciones del ciclo de vida de Unit. Consulta [Identidad y autorización](https://docs.univer.ai/es-ES/server/collaboration/identity-and-authorization.md) para la cobertura completa.

### 4. Registrar el cliente Collaboration en Runtime del navegador

Conserva Web SDK y los presets habituales y añade los plugins de colaboración y las URL del protocolo:

```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,
  ],
});

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

La página necesita un elemento con `id="app"` y selecciona la Unit mediante parámetros de consulta:

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

### 5. Sustituir la configuración didáctica

| Configuración didáctica     | Sustitución                                                                |
| --------------------------- | -------------------------------------------------------------------------- |
| `demo-user` fijo            | Middleware de autenticación e ID de usuario estable                        |
| Permisos siempre permitidos | ACL del servidor para lectura, JOIN, envío y ciclo de vida                 |
| Unit fija                   | API de creación y registro de producto que llamen a `createUnitFromData()` |
| Memory Adapter              | SQLite o Adapter persistente propio con pruebas de contrato                |

Completa [Adaptadores de base de datos](https://docs.univer.ai/es-ES/server/collaboration/database-adapters.md) e [Identidad y autorización](https://docs.univer.ai/es-ES/server/collaboration/identity-and-authorization.md). Añade [History, Thread Comment, Worktree o Exchange](https://docs.univer.ai/es-ES/server/collaboration/extensions.md) según sea necesario. Consulta todas las composiciones ejecutables en el [índice de ejemplos](https://docs.univer.ai/es-ES/server/collaboration/examples.md).

## Resolver problemas del primer inicio

| Síntoma                            | Comprobación                                                                                               |
| ---------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| Fallo de instalación o compilación | Node.js 24+, pnpm declarado, versiones Univer iguales                                                      |
| Puerto 3010 ocupado                | Detener el ejemplo anterior o usar `PORT=3011` y actualizar ambas URL                                      |
| Página vacía o recursos ausentes   | Compilación terminada, inicio desde el directorio del ejemplo, altura de `#app`                            |
| Los cambios no se sincronizan      | Misma URL completa, snapshot y session-ticket correctos, WebSocket `/universer-api/comb/connect` conectado |
| Datos perdidos al reiniciar        | Quick Start usa memoria; continuar con SQLite                                                              |
