Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/externalize-yjs-peer-dependency.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@tumaet/apollon": minor
---

Two packaging improvements for embedding hosts. First, `yjs` and `y-protocols` are now required peer dependencies instead of being bundled, so your app and Apollon share a single Yjs instance — no duplicate payload and no cross-instance document errors. Second, a new `@tumaet/apollon/external` entry exposes the same imperative `ApollonEditor` API as the default entry but leaves **every** dependency external (React, MUI, emotion, xyflow, @dnd-kit, zustand, uuid, @chenglou/pretext, …) — so a bundler host of any framework resolves and de-duplicates each one from its own `node_modules` and gets full supply-chain / SBOM visibility, instead of a copy inlined invisibly into the bundle. The default `@tumaet/apollon` (self-contained) and `@tumaet/apollon/react` entries are unchanged. Action required only if you adopt the new entry or the Yjs peer: install the corresponding peers (most package managers do this automatically).
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@ This monorepo contains every piece of the Apollon platform:
## Use the library

```sh
npm install @tumaet/apollon
npm install @tumaet/apollon yjs y-protocols
```

See the [library README](./library/README.md) for the API.
`yjs` and `y-protocols` are required peer dependencies — they power Apollon's
document model and undo/redo (and live collaboration when enabled), kept
external so the host owns a single Yjs instance. See the
[library README](./library/README.md) for the API and the other build entries.

## Run the stack locally

Expand Down
4 changes: 2 additions & 2 deletions docs/library/embedding/angular.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ description: Embed Apollon in an Angular host using the default standalone bundl
# Angular

Use the **standalone subpath** (`@tumaet/apollon`). Angular hosts get the
editor with **zero peer deps** to install — React is bundled inside the
tarball.
editor with React bundled inside the tarball; the only peers to install are
`yjs` and `y-protocols` (`npm install @tumaet/apollon yjs y-protocols`).

```ts
import {
Expand Down
53 changes: 45 additions & 8 deletions docs/library/embedding/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,32 @@ description: Install @tumaet/apollon — pick the standalone or /react subpath.

# Install

`yjs` and `y-protocols` are required peer dependencies of **every** build — they
power Apollon's document model and undo/redo (and live collaboration when
enabled), so the editor needs them whether or not you collaborate. Keeping them
external lets a host that already uses Yjs share a single instance instead of a
private, possibly mismatched copy. Most package managers install missing peers
automatically.

## Standalone build (any framework)

```sh
npm install @tumaet/apollon
npm install @tumaet/apollon yjs y-protocols
```

```ts
import { ApollonEditor } from "@tumaet/apollon"
import "@tumaet/apollon/style.css"
```

No further installs — React, MUI, emotion, and xyflow are bundled inside the library tarball.
React, MUI, emotion, and xyflow are bundled inside the library tarball; only
`yjs` and `y-protocols` are peers you provide.

## Peer-dependency build (React hosts)

```sh
npm install @tumaet/apollon \
yjs y-protocols \
react react-dom \
@emotion/react @emotion/styled @mui/material @xyflow/react
```
Expand All @@ -32,19 +41,47 @@ import { ApollonEditor } from "@tumaet/apollon/react"
import "@tumaet/apollon/style.css"
```

`yjs` and `y-protocols` are required for every build; the React, MUI, emotion,
and xyflow peers below are needed by the `/react` and `/external` builds.

| Peer | Range |
| ----------------- | ---------- |
| `react` | `^18.3.0` |
| `react-dom` | `^18.3.0` |
| `yjs` | `^13.6.0` |
| `y-protocols` | `^1.0.6` |
| `react` | `^19.0.0` |
| `react-dom` | `^19.0.0` |
| `@mui/material` | `^6.4.0` |
| `@emotion/react` | `^11.11.0` |
| `@emotion/styled` | `^11.11.0` |
| `@xyflow/react` | `^12.3.0` |
| `@emotion/react` | `^11.12.0` |
| `@emotion/styled` | `^11.12.0` |
| `@xyflow/react` | `^12.9.0` |

The `/react` subpath keeps your final bundle from shipping a second copy of
React. It is also the entry that exports the `<Apollon>` React component — the
recommended way to embed in React. See [React](/library/embedding/react).

## Fully external build (any bundler host)

```sh
npm install @tumaet/apollon \
yjs y-protocols \
react react-dom \
@emotion/react @emotion/styled @mui/material @xyflow/react
```

```ts
import { ApollonEditor } from "@tumaet/apollon/external"
import "@tumaet/apollon/style.css"
```

Same imperative `ApollonEditor` API as the default entry, but **every**
dependency is external — the React family above _and_ Apollon's own runtime
deps (`@dnd-kit`, `zustand`, `uuid`, `@chenglou/pretext`), which arrive
transitively with the package. Your bundler resolves and de-duplicates each one
against your app's `node_modules`, and your bundle analyzer / SBOM tooling sees
them as real packages instead of code inlined invisibly into one chunk. Use it
from any framework with a bundler, including non-React ones (the editor still
runs on the React you provide internally; your own code never touches it).

## Type definitions

Types ship with the package (`dist/index.d.ts`) and are identical for both subpaths. Requires TypeScript 5.0+ with `moduleResolution: "bundler" | "node16" | "nodenext"`.
Types ship with the package (`dist/index.d.ts`) and are identical for every subpath. Requires TypeScript 5.0+ with `moduleResolution: "bundler" | "node16" | "nodenext"`.
5 changes: 5 additions & 0 deletions docs/library/embedding/vanilla.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ description: Drop Apollon into a plain HTML page with one script tag.
The standalone subpath works as a single ESM module loaded directly from a
CDN. No build step, no bundler.

`yjs` and `y-protocols` are required peers, but on the CDN path esm.sh resolves
and serves them from the import URL automatically — there is nothing extra to
load. (With a bundler you install the peers yourself — see
[Install](/library/embedding/install).)

```html
<link rel="stylesheet" href="https://esm.sh/@tumaet/apollon@4.8.0/style.css" />
<div id="apollon" style="width: 100%; height: 600px"></div>
Expand Down
13 changes: 7 additions & 6 deletions docs/library/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ Apollon ships as an npm library that any framework can embed. The public API is

13 UML and modeling diagram types · SVG/PNG/PDF/JSON export · optional real-time collaboration via Yjs · injectable [canvas overlay controls](/library/api/overlay-controls).

## Two builds, one API
## Three builds, one API

| Subpath | React / MUI / emotion / xyflow | Bundle | When to use |
| ----------------------------- | ------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `@tumaet/apollon` _(default)_ | bundled | ~2.4 MB | Any framework that doesn't already have React installed — Angular (the primary use case for [Artemis](https://artemis.tum.de/)), Vue, Svelte, vanilla JS. Zero peer deps to install. |
| `@tumaet/apollon/react` | externalized | ~875 KB | React 18.3 hosts that want to share their React instance with the editor and dedupe the bundle. |
| Subpath | Dependencies | Bundle | When to use |
| ----------------------------- | ------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `@tumaet/apollon` _(default)_ | all bundled (except Yjs) | ~2.4 MB | No bundler — vanilla JS, a `<script>` tag, or a CDN. Self-contained; only `yjs` + `y-protocols` to install. |
| `@tumaet/apollon/react` | React family external | ~875 KB | A React host that shares its own React/MUI and wants the `<Apollon>` component. |
| `@tumaet/apollon/external` | everything external | ~840 KB | A bundler host of any framework — Angular, Vue, Svelte, React — that wants one shared, fully auditable copy of every dependency. |

`peerDependenciesMeta.optional` covers all six peers `npm install @tumaet/apollon` never warns about missing React.
`peerDependenciesMeta.optional` covers the six React-family peers, so `npm install @tumaet/apollon` never warns about missing React. `yjs` and `y-protocols` are required peers of all builds — they power Apollon's document model and undo/redo (and live collaboration when enabled), so the editor needs them either way, and keeping them external lets a host that already uses Yjs own a single instance. Most package managers add them automatically. The `/external` entry additionally externalizes Apollon's own runtime deps (`@dnd-kit`, `zustand`, `uuid`, `@chenglou/pretext`), which install transitively with the package.

## What's next

Expand Down
9 changes: 6 additions & 3 deletions docs/library/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ idiomatic version — but the two steps below are all Apollon needs.
## 1. Install

```sh
npm install @tumaet/apollon
npm install @tumaet/apollon yjs y-protocols
```

This is the standalone build: React, MUI, emotion, and xyflow are bundled
inside the tarball, so there are no peer dependencies to install. React hosts
should instead use the `/react` subpath — see [Install](/library/embedding/install).
inside the tarball; `yjs` and `y-protocols` are the only peers you install. They
power Apollon's document model and undo/redo (and live collaboration when
enabled), kept external so a host that already uses Yjs shares one instance.
React hosts should instead use the `/react` subpath — see
[Install](/library/embedding/install).

:::danger The editor MUST have an explicit height
Apollon renders onto a React Flow canvas, which sizes itself to its parent. If
Expand Down
10 changes: 7 additions & 3 deletions docs/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ const VANILLA_SNIPPET = `<link
<div id="apollon" style="width: 100%; height: 600px"></div>

<script type="module">
// esm.sh serves Apollon's required yjs/y-protocols peers automatically.
import { ApollonEditor } from "https://esm.sh/@tumaet/apollon@4.8.0"

const saved = localStorage.getItem("diagram")
Expand Down Expand Up @@ -111,7 +112,9 @@ function Hero() {
</Link>
</div>
<div className={styles.install}>
<CodeBlock language="bash">npm install @tumaet/apollon</CodeBlock>
<CodeBlock language="bash">
npm install @tumaet/apollon yjs y-protocols
</CodeBlock>
</div>
</div>
</header>
Expand Down Expand Up @@ -224,8 +227,9 @@ const WAYS: LinkCard[] = [
body: (
<>
<code>@tumaet/apollon</code> on npm. Framework-agnostic by default;
Angular hosts install <strong>zero peer deps</strong>. A{" "}
<code>/react</code> subpath dedupes React when the host already has it.
Angular hosts install just <code>yjs</code> + <code>y-protocols</code>.
A <code>/react</code> subpath dedupes React when the host already has
it.
</>
),
to: "/library/",
Expand Down
2 changes: 1 addition & 1 deletion docs/user/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ versioned and reviewed like any other source.
you need UML modeling inside an existing application.

```sh
npm install @tumaet/apollon
npm install @tumaet/apollon yjs y-protocols
```

| You want to... | Use this |
Expand Down
60 changes: 42 additions & 18 deletions library/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,32 +29,36 @@ Apollon is the modeling editor behind [Artemis](https://artemis.tum.de/), TUM's

## Install

The package ships two builds with the same API. Pick one based on whether your host already uses React:
The package ships three builds with the same imperative API. Pick one based on how your host bundles (or doesn't):

| Import | React / MUI / emotion / xyflow | Size (min / gzip) | Use when |
| ----------------------------- | ------------------------------ | ----------------- | ------------------------------------------------------------------------------------------------------- |
| `@tumaet/apollon` _(default)_ | **bundled** | ~2.4 MB / ~540 KB | Your host is Angular, Vue, Svelte, or vanilla JS. No peer deps to install. |
| `@tumaet/apollon/react` | **peer deps** (shared) | ~875 KB / ~170 KB | Your host is React 18.3 and should share its React and MUI with the editor instead of duplicating them. |
| Import | Dependencies | Size (min / gzip) | Use when |
| ----------------------------- | ---------------------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `@tumaet/apollon` _(default)_ | **all bundled** (except Yjs) | ~2.4 MB / ~540 KB | No bundler — vanilla JS, a `<script>` tag, or a CDN. Self-contained; only `yjs` + `y-protocols` to install. |
| `@tumaet/apollon/react` | **React family external** | ~875 KB / ~170 KB | A React host that shares its own React and MUI with the editor. Also ships the `<Apollon>` component, hooks, provider. |
| `@tumaet/apollon/external` | **everything external** | ~840 KB / ~175 KB | A bundler host (Angular, Vue, Svelte, React) that wants every dependency resolved from its own `node_modules` — one shared copy and full SBOM / audit visibility. |

Sizes are the published entry chunks. Gzip is the transfer size. The `/react` number excludes the peers your app already ships.
Sizes are the published entry chunks. Gzip is the transfer size. The `/react` and `/external` numbers exclude the peers your app already ships.

### Standalone build (any framework, no peer deps)
`yjs` and `y-protocols` are required peer dependencies of **all three** builds — they power Apollon's document model and undo/redo (and live collaboration when you enable it), so every editor needs them, collaboration or not. Keeping them external means a host that already uses Yjs (or a second Apollon on the page) shares a single Yjs instance instead of loading a private, possibly mismatched copy. Most package managers install missing peers automatically; the explicit commands below are listed for clarity.

### Standalone build (any framework)

```sh
npm install @tumaet/apollon
npm install @tumaet/apollon yjs y-protocols
```

```ts
import { ApollonEditor } from "@tumaet/apollon"
import "@tumaet/apollon/style.css"
```

React, MUI, emotion, and xyflow are bundled in. Nothing else to install.
React, MUI, emotion, and xyflow are bundled in; only `yjs` and `y-protocols` are peers you provide.

### React build (share your host's React)

```sh
npm install @tumaet/apollon \
yjs y-protocols \
react react-dom \
@emotion/react @emotion/styled @mui/material @xyflow/react
```
Expand All @@ -64,18 +68,36 @@ import { Apollon } from "@tumaet/apollon/react"
import "@tumaet/apollon/style.css"
```

| Peer | Range | | Peer | Range |
| --------------- | --------- | --- | ----------------- | ---------- |
| `react` | `^18.3.0` | | `@mui/material` | `^6.4.0` |
| `react-dom` | `^18.3.0` | | `@emotion/react` | `^11.11.0` |
| `@xyflow/react` | `^12.3.0` | | `@emotion/styled` | `^11.11.0` |
`yjs` and `y-protocols` are required for all builds; the React, MUI, emotion, and xyflow peers below are specific to the `/react` and `/external` builds.

## Which build do I use?
| Peer | Range | | Peer | Range |
| ------------- | --------- | --- | ----------------- | ---------- |
| `yjs` | `^13.6.0` | | `@mui/material` | `^6.4.0` |
| `y-protocols` | `^1.0.6` | | `@emotion/react` | `^11.12.0` |
| `react` | `^19.0.0` | | `@emotion/styled` | `^11.12.0` |
| `react-dom` | `^19.0.0` | | `@xyflow/react` | `^12.9.0` |

### Fully external build (any bundler host)

```sh
npm install @tumaet/apollon \
yjs y-protocols \
react react-dom \
@emotion/react @emotion/styled @mui/material @xyflow/react
```

```ts
import { ApollonEditor } from "@tumaet/apollon/external"
import "@tumaet/apollon/style.css"
```

Same imperative `ApollonEditor` API as the default entry, but **every** dependency is left external — the React family above _and_ Apollon's own runtime deps (`@dnd-kit`, `zustand`, `uuid`, `@chenglou/pretext`), which arrive transitively when you install the package. Your bundler then resolves and de-duplicates each one against your app's `node_modules`, and your bundle analyzer / SBOM tooling sees them as the real packages they are instead of code inlined invisibly into one chunk. Use this from any framework with a bundler — even a non-React one (the editor still runs on the React you provide internally; your own code never touches it).

It comes down to whether your host already runs React:
## Which build do I use?

- **Not a React app?** Use the default `@tumaet/apollon`. It bundles its own React, so there is nothing extra to install or configure.
- **A React app?** Use `@tumaet/apollon/react` and install the peers above. The default build bundles its own React, so in a React app you would load two copies. That causes "Invalid hook call" errors and a larger bundle. The `/react` subpath leaves React, MUI, emotion, and xyflow external so the editor shares the copies your app already has. It is also the only entry that exports the `<Apollon>` component, hooks, and provider.
- **No bundler** (vanilla JS, `<script>`, CDN)? Use the default `@tumaet/apollon`. It inlines its own React, so the only peers to install are `yjs` and `y-protocols`.
- **A React app?** Use `@tumaet/apollon/react` and install the peers above. The default build bundles its own React, so in a React app you would load two copies — that causes "Invalid hook call" errors and a larger bundle. The `/react` subpath leaves React, MUI, emotion, and xyflow external so the editor shares the copies your app already has. It is also the only entry that exports the `<Apollon>` component, hooks, and provider.
- **A bundler host that wants one shared, fully auditable copy of every dependency?** Use `@tumaet/apollon/external` and install the peers above. Works from any framework.

> **⚠️ Give the container an explicit, non-zero height** (`600px`, `80vh`, or a sized flex/grid child), whichever build you use. The canvas sizes itself to its parent, so with no resolvable height it collapses to zero pixels and renders blank. This is the most common embedding mistake. See [Troubleshooting](https://ls1intum.github.io/Apollon/library/troubleshooting).

Expand Down Expand Up @@ -178,6 +200,8 @@ export class DiagramEditorComponent {

### Vanilla JS / CDN

`yjs` and `y-protocols` are required peers, but on the CDN path esm.sh resolves and serves them from the import URL automatically — there is nothing extra to load. (With a bundler you install the peers yourself.)

```html
<link rel="stylesheet" href="https://esm.sh/@tumaet/apollon@4.8.0/style.css" />
<div id="apollon" style="width: 100%; height: 600px"></div>
Expand Down
Loading
Loading