@thatopen/services 0.3.16 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +62 -62
  2. package/dist/cli/commands/rhino.d.ts +11 -0
  3. package/dist/cli/lib/plugin-install.d.ts +24 -0
  4. package/dist/cli.js +124 -1
  5. package/dist/core/client.d.ts +1 -0
  6. package/dist/core/platform-client.d.ts +7 -0
  7. package/dist/index.cjs.js +2 -2
  8. package/dist/index.es.js +382 -370
  9. package/dist/vite-env.d.ts +1 -1
  10. package/docs/ai-quickstart.md +130 -130
  11. package/docs/cli/create.md +29 -29
  12. package/docs/cli/local-server.md +38 -38
  13. package/docs/cli/login.md +32 -32
  14. package/docs/cli/publish.md +31 -31
  15. package/docs/cli/run.md +26 -26
  16. package/docs/cli/serve.md +43 -43
  17. package/docs/cli/swap.md +30 -30
  18. package/docs/cloud/GaussianSplatConverter.md +43 -43
  19. package/docs/cloud/PointCloudConverter.md +53 -53
  20. package/docs/revit-collab-quickstart.md +256 -256
  21. package/package.json +95 -95
  22. package/resources/AGENTS.md +40 -40
  23. package/src/built-in/CDEManager/example.ts +214 -214
  24. package/src/built-in/CDEManager/examples/FileEditing/example.ts +226 -226
  25. package/src/built-in/CDEManager/examples/FileMoves/example.ts +186 -186
  26. package/src/built-in/CDEManager/examples/FileOperations/example.ts +295 -295
  27. package/src/built-in/CDEManager/examples/FileTransfers/example.ts +210 -210
  28. package/src/built-in/CDEManager/examples/FolderManagement/example.ts +230 -230
  29. package/src/built-in/CDEManager/examples/MetadataSchema/example.ts +230 -230
  30. package/src/built-in/CDEManager/examples/MetadataViews/example.ts +166 -166
  31. package/src/built-in/CDEManager/examples/ProjectConfig/example.ts +177 -177
  32. package/src/built-in/ClashesManager/example.ts +283 -283
  33. package/src/built-in/UIManager/src/app/example.ts +97 -97
  34. package/src/built-in/UIManager/src/app/examples/AppState/example.ts +140 -140
  35. package/src/built-in/UIManager/src/app/examples/Banner/example.ts +159 -159
  36. package/src/built-in/UIManager/src/app/examples/Contexts/example.ts +123 -123
  37. package/src/built-in/UIManager/src/app/examples/FileDrop/example.ts +124 -124
  38. package/src/built-in/UIManager/src/app/examples/FloatingLayout/example.ts +90 -90
  39. package/src/built-in/UIManager/src/app/examples/Modal/example.ts +163 -163
  40. package/src/built-in/UIManager/src/app/examples/Notifications/example.ts +133 -133
  41. package/src/built-in/UIManager/src/app/examples/Sidebar/example.ts +102 -102
  42. package/src/cli/templates/app/README.md +217 -217
  43. package/src/cli/templates/app/index.html +35 -35
  44. package/src/cli/templates/app/package.json +32 -32
  45. package/src/cli/templates/app/src/app.ts +37 -37
  46. package/src/cli/templates/app/src/assets/tool-placeholder.ts +50 -50
  47. package/src/cli/templates/app/src/bim-components/CloudRunner/index.ts +95 -95
  48. package/src/cli/templates/app/src/bim-components/CloudRunner/src/index.ts +1 -1
  49. package/src/cli/templates/app/src/bim-components/CloudRunner/src/types.ts +5 -5
  50. package/src/cli/templates/app/src/bim-components/index.ts +1 -1
  51. package/src/cli/templates/app/src/globals.ts +1 -1
  52. package/src/cli/templates/app/src/main.ts +199 -199
  53. package/src/cli/templates/app/src/setups/reality-capture/lib/hidden-tiles-plugin.ts +88 -88
  54. package/src/cli/templates/app/src/setups/reality-capture/lib/point-tile-plugin.ts +166 -166
  55. package/src/cli/templates/app/src/setups/reality-capture/lib/render-frame.ts +31 -31
  56. package/src/cli/templates/app/src/setups/reality-capture/lib/splat-tile-plugin.ts +51 -51
  57. package/src/cli/templates/app/src/setups/reality-capture-viewer.ts +1383 -1383
  58. package/src/cli/templates/app/src/ui-components/app-info-section/index.ts +26 -26
  59. package/src/cli/templates/app/src/ui-components/app-info-section/src/index.ts +1 -1
  60. package/src/cli/templates/app/src/ui-components/app-info-section/src/types.ts +15 -15
  61. package/src/cli/templates/app/src/ui-components/cloud-runner-section/index.ts +37 -37
  62. package/src/cli/templates/app/src/ui-components/cloud-runner-section/src/index.ts +1 -1
  63. package/src/cli/templates/app/src/ui-components/cloud-runner-section/src/types.ts +14 -14
  64. package/src/cli/templates/app/src/ui-components/index.ts +2 -2
  65. package/src/cli/templates/app/tsconfig.json +16 -16
  66. package/src/cli/templates/app/vite.config.js +57 -57
  67. package/src/cli/templates/cloud-component/README.md +205 -205
  68. package/src/cli/templates/cloud-component/_thatopen +5 -5
  69. package/src/cli/templates/cloud-component/declarations.json +4 -4
  70. package/src/cli/templates/cloud-component/package.json +21 -21
  71. package/src/cli/templates/cloud-component/src/main.ts +70 -70
  72. package/src/cli/templates/cloud-component/tsconfig.json +16 -16
  73. package/src/cli/templates/cloud-component/vite.config.js +46 -46
  74. package/src/cli/templates/shared/AGENTS.md +8 -8
  75. package/src/cli/templates/shared/CLAUDE.md +1 -1
  76. package/src/cli/templates/shared/_gitignore +5 -5
@@ -1,102 +1,102 @@
1
- /* MD
2
- ## Sidebar navigation
3
- ---
4
- Product teams building BIM apps often need multiple distinct views — a 3D model
5
- viewer, a data browser, a settings screen — but wiring a custom nav bar and
6
- managing view transitions from scratch adds complexity before any real feature
7
- work begins.
8
-
9
- top-app supports named layouts with a built-in sidebar navigation bar that
10
- switches the active grid template on click, so teams get multi-view navigation
11
- without building the scaffolding themselves.
12
-
13
- This tutorial covers defining three named layouts with their own grid templates
14
- and icons; providing a dedicated element for each view; enabling the sidebar nav
15
- bar; and setting the initial active layout.
16
-
17
- By the end, you'll have a multi-view BIM app with a persistent sidebar that lets
18
- users switch between a 3D viewer, a data panel, and a settings screen.
19
- */
20
-
21
- import { html } from "lit";
22
- import * as THREE from "three";
23
- import * as OBC from "@thatopen/components";
24
- import * as OBF from "@thatopen/components-front";
25
- import * as FRAGS from "@thatopen/fragments";
26
- import * as BUI from "@thatopen/ui";
27
- import { PlatformClient, UIManager } from "@thatopen/services";
28
- import type { App } from "../../index";
29
-
30
- const client = PlatformClient.fromPlatformContext();
31
- const { components } = (await client.setup(
32
- { OBC, OBF, BUI, THREE, FRAGS },
33
- { uuid: UIManager.uuid },
34
- )) as { components: OBC.Components };
35
- components.get(UIManager).init();
36
-
37
- const app = document.createElement("top-app") as unknown as App;
38
-
39
- app.setup = (waitUntil) => {
40
- waitUntil(
41
- (async () => {
42
- const fragments = components.get(OBC.FragmentsManager);
43
- const workerUrl = await FRAGS.FragmentsModels.getWorker();
44
- fragments.init(await FRAGS.toClassicWorker(workerUrl), {
45
- classicWorker: true,
46
- });
47
- })(),
48
- "Fragments Core",
49
- );
50
- return { components, client };
51
- };
52
-
53
- app.elements = {
54
- viewer: () =>
55
- html`<top-viewer><top-viewer-tools></top-viewer-tools></top-viewer>`,
56
-
57
- data: () => html`
58
- <bim-panel label="Data">
59
- <bim-panel-section label="Properties" icon="solar:document-bold">
60
- <bim-label>Select an element in the viewer to inspect its properties.</bim-label>
61
- </bim-panel-section>
62
- </bim-panel>
63
- `,
64
-
65
- settings: () => html`
66
- <bim-panel label="Settings">
67
- <bim-panel-section label="Appearance" icon="solar:settings-bold">
68
- <bim-checkbox label="Show grid" checked></bim-checkbox>
69
- <bim-checkbox label="Show axes"></bim-checkbox>
70
- </bim-panel-section>
71
- </bim-panel>
72
- `,
73
- };
74
-
75
- app.layouts = {
76
- // Each layout defines its own CSS grid template. Only areas used in a template
77
- // are rendered for that layout — unused elements are not created.
78
- viewer: {
79
- label: "Viewer",
80
- icon: "solar:3d-square-bold",
81
- template: `"viewer" 1fr / 1fr`,
82
- },
83
- data: {
84
- label: "Data",
85
- icon: "solar:document-bold",
86
- template: `"data" 1fr / 1fr`,
87
- },
88
- settings: {
89
- label: "Settings",
90
- icon: "solar:settings-bold",
91
- template: `"settings" 1fr / 1fr`,
92
- },
93
- };
94
-
95
- // sidebar=true adds a vertical nav column on the left with one button per layout.
96
- // Each button shows the layout's label and icon and activates that layout on click.
97
- app.sidebar = true;
98
- app.layout = "viewer";
99
-
100
- const container = document.getElementById("that-open-app") ?? document.body;
101
- container.appendChild(app);
102
- document.body.style.margin = "0";
1
+ /* MD
2
+ ## Sidebar navigation
3
+ ---
4
+ Product teams building BIM apps often need multiple distinct views — a 3D model
5
+ viewer, a data browser, a settings screen — but wiring a custom nav bar and
6
+ managing view transitions from scratch adds complexity before any real feature
7
+ work begins.
8
+
9
+ top-app supports named layouts with a built-in sidebar navigation bar that
10
+ switches the active grid template on click, so teams get multi-view navigation
11
+ without building the scaffolding themselves.
12
+
13
+ This tutorial covers defining three named layouts with their own grid templates
14
+ and icons; providing a dedicated element for each view; enabling the sidebar nav
15
+ bar; and setting the initial active layout.
16
+
17
+ By the end, you'll have a multi-view BIM app with a persistent sidebar that lets
18
+ users switch between a 3D viewer, a data panel, and a settings screen.
19
+ */
20
+
21
+ import { html } from "lit";
22
+ import * as THREE from "three";
23
+ import * as OBC from "@thatopen/components";
24
+ import * as OBF from "@thatopen/components-front";
25
+ import * as FRAGS from "@thatopen/fragments";
26
+ import * as BUI from "@thatopen/ui";
27
+ import { PlatformClient, UIManager } from "@thatopen/services";
28
+ import type { App } from "../../index";
29
+
30
+ const client = PlatformClient.fromPlatformContext();
31
+ const { components } = (await client.setup(
32
+ { OBC, OBF, BUI, THREE, FRAGS },
33
+ { uuid: UIManager.uuid },
34
+ )) as { components: OBC.Components };
35
+ components.get(UIManager).init();
36
+
37
+ const app = document.createElement("top-app") as unknown as App;
38
+
39
+ app.setup = (waitUntil) => {
40
+ waitUntil(
41
+ (async () => {
42
+ const fragments = components.get(OBC.FragmentsManager);
43
+ const workerUrl = await FRAGS.FragmentsModels.getWorker();
44
+ fragments.init(await FRAGS.toClassicWorker(workerUrl), {
45
+ classicWorker: true,
46
+ });
47
+ })(),
48
+ "Fragments Core",
49
+ );
50
+ return { components, client };
51
+ };
52
+
53
+ app.elements = {
54
+ viewer: () =>
55
+ html`<top-viewer><top-viewer-tools></top-viewer-tools></top-viewer>`,
56
+
57
+ data: () => html`
58
+ <bim-panel label="Data">
59
+ <bim-panel-section label="Properties" icon="solar:document-bold">
60
+ <bim-label>Select an element in the viewer to inspect its properties.</bim-label>
61
+ </bim-panel-section>
62
+ </bim-panel>
63
+ `,
64
+
65
+ settings: () => html`
66
+ <bim-panel label="Settings">
67
+ <bim-panel-section label="Appearance" icon="solar:settings-bold">
68
+ <bim-checkbox label="Show grid" checked></bim-checkbox>
69
+ <bim-checkbox label="Show axes"></bim-checkbox>
70
+ </bim-panel-section>
71
+ </bim-panel>
72
+ `,
73
+ };
74
+
75
+ app.layouts = {
76
+ // Each layout defines its own CSS grid template. Only areas used in a template
77
+ // are rendered for that layout — unused elements are not created.
78
+ viewer: {
79
+ label: "Viewer",
80
+ icon: "solar:3d-square-bold",
81
+ template: `"viewer" 1fr / 1fr`,
82
+ },
83
+ data: {
84
+ label: "Data",
85
+ icon: "solar:document-bold",
86
+ template: `"data" 1fr / 1fr`,
87
+ },
88
+ settings: {
89
+ label: "Settings",
90
+ icon: "solar:settings-bold",
91
+ template: `"settings" 1fr / 1fr`,
92
+ },
93
+ };
94
+
95
+ // sidebar=true adds a vertical nav column on the left with one button per layout.
96
+ // Each button shows the layout's label and icon and activates that layout on click.
97
+ app.sidebar = true;
98
+ app.layout = "viewer";
99
+
100
+ const container = document.getElementById("that-open-app") ?? document.body;
101
+ container.appendChild(app);
102
+ document.body.style.margin = "0";
@@ -1,217 +1,217 @@
1
- # ThatOpen BIM App
2
-
3
- This is a BIM (Building Information Modeling) app built for the That Open Platform.
4
- It runs in the browser inside the platform's iframe and has access to a 3D viewer,
5
- UI components, and the platform API.
6
-
7
- > IMPORTANT for AI assistants: the authoritative, always-current reference for the
8
- > platform rules, the built-in components, and how to wire each one is shipped
9
- > inside the installed package. Read these before writing code:
10
- >
11
- > - `node_modules/@thatopen/services/resources/AGENTS.md` — platform rules + the
12
- > full navigation table.
13
- > - `node_modules/@thatopen/services/docs/builtin/paths.json` — the index of every
14
- > built-in component, with a one-line description and the path to its example.
15
- > - `node_modules/@thatopen/services/src/built-in/<Component>/example.ts` — a
16
- > complete, copy-adaptable integration example per component.
17
- >
18
- > This README explains the app's shape and the general pattern. For the exact API
19
- > of any built-in, trust `paths.json` + the example files over any list here.
20
-
21
- ## How this app works
22
-
23
- - **Entry point**: `src/main.ts` — runs as an IIFE when the platform loads the app.
24
- - **Build output**: `dist/bundle.js` — a single IIFE file.
25
- - **Platform context**: the platform injects the app's context (project id, access
26
- token, API url). `PlatformClient.fromPlatformContext()` reads it for you.
27
-
28
- ## Commands
29
-
30
- ```bash
31
- npm run dev # Start the dev server (esbuild watch + serve on :4000)
32
- npm run build # Build dist/bundle.js
33
- npm run login # Authenticate with the platform (saves token locally)
34
- npm run publish # Publish to the platform
35
- ```
36
-
37
- ### Local development
38
-
39
- Apps run inside the That Open Platform within a project, not as standalone websites.
40
- To develop locally:
41
-
42
- 1. Run `npm run dev` — watches source with esbuild and serves the bundle on port 4000.
43
- 2. Open your project on the platform and click the debug button.
44
- 3. Live reload is enabled — save a file to rebuild automatically.
45
-
46
- **Important**: use `npm run dev` (it runs `thatopen serve` under the hood). Do NOT run
47
- `vite` / `vite build --watch` directly for development — `thatopen serve` applies the
48
- correct build settings (including the beta engine-library aliases for beta projects).
49
-
50
- ## Key libraries
51
-
52
- | Package | Import as | Purpose |
53
- |---------|-----------|---------|
54
- | `@thatopen/components` | `OBC` | BIM engine — components, fragments, worlds |
55
- | `@thatopen/components-front` | `OBF` | Front-end BIM components (Highlighter, measurements, …) |
56
- | `@thatopen/fragments` | `FRAGS` | Fragment geometry format |
57
- | `@thatopen/ui` | `BUI` | UI web components (`<bim-panel>`, `<bim-grid>`, …) |
58
- | `three` | `THREE` | 3D rendering engine |
59
- | `@markerjs/markerjs3` | `MARKERJS` | Screenshot annotation |
60
- | `@thatopen/services` | (named exports) | Platform API client (`PlatformClient`) + built-in components |
61
-
62
- ```ts
63
- import * as OBC from "@thatopen/components";
64
- import * as OBF from "@thatopen/components-front";
65
- import * as FRAGS from "@thatopen/fragments";
66
- import * as BUI from "@thatopen/ui";
67
- import * as THREE from "three";
68
- import * as MARKERJS from "@markerjs/markerjs3";
69
- import { PlatformClient, UIManager } from "@thatopen/services";
70
- ```
71
-
72
- ## Architecture
73
-
74
- The app boots on the **`UIManager`** built-in. `UIManager` registers the platform's
75
- web components — the app shell and viewport plus every panel — as custom elements you
76
- place with plain HTML/`BUI.html`:
77
-
78
- - `<top-app>` — the app shell: a CSS-grid layout system with a sidebar (activity bar)
79
- for switching named layouts.
80
- - `<top-viewer>` — the 3D viewport (pre-configured world: scene, camera, renderer,
81
- fragments), with its own tools baked in.
82
- - `<top-viewer-toolbar>` — the bottom viewer toolbar (visibility/inspect, clip, measure).
83
- - Side panels — `<top-model-tree>`, `<top-properties-panel>`, `<top-models-list>`,
84
- `<top-data-table-panel>`, `<top-objects-panel>`, `<top-settings-panel>`, … — each
85
- self-wires from the contexts `<top-app>` provides (no `components` plumbing needed).
86
-
87
- The scaffolded `src/main.ts` already sets this up. The shape is:
88
-
89
- ```ts
90
- const client = PlatformClient.fromPlatformContext();
91
-
92
- // 1. Register the platform web components. UIManager MUST be in setup — it
93
- // defines <top-app>, <top-viewer>, the panels, etc. before the DOM renders.
94
- const { components } = await client.setup<OBC.Components>(
95
- { OBC, OBF, BUI, THREE, FRAGS, MARKERJS },
96
- { uuid: UIManager.uuid },
97
- );
98
- components.get(UIManager).init();
99
-
100
- // 2. Build the shell: <top-app> with named element slots + named layouts.
101
- const app = document.createElement("top-app") as any;
102
- app.elements = {
103
- viewer: () => BUI.html`<top-viewer></top-viewer>`,
104
- tree: () => BUI.html`<top-model-tree></top-model-tree>`,
105
- // …more panels…
106
- };
107
- app.layouts = {
108
- Explorer: { icon: "mdi:file-tree", template: `"tree viewer" 1fr / 22rem 1fr` },
109
- // …more layouts…
110
- };
111
- app.layout = "Explorer";
112
- app.sidebar = true;
113
- document.getElementById("that-open-app")?.appendChild(app);
114
- ```
115
-
116
- A layout `template` is CSS `grid-template` shorthand: `"areas" rows / columns`, where
117
- each area name maps to a key in `app.elements`. Each layout with an `icon` becomes a
118
- sidebar (activity-bar) button.
119
-
120
- Built-ins are loaded from the platform at runtime **by uuid** through the `setup`
121
- call. You import each one as a named export from `@thatopen/services` (a ready
122
- `{ uuid }` stub with types), never by a deep/internal path.
123
-
124
- ## Built-in components
125
-
126
- The current, authoritative list lives in
127
- `node_modules/@thatopen/services/docs/builtin/paths.json` (index) with a full example
128
- per component under `node_modules/@thatopen/services/src/built-in/`. At a high level:
129
-
130
- - **`UIManager`** — the shell + viewport + all `top-*` panels above (already wired by
131
- the scaffold).
132
- - **`CDEManager`** — the platform CDE: files, folders, versions, metadata.
133
- - **`ClashesManager`** + `<top-clashes-panel>` — clash detection and the ready-made
134
- clash review UI (detection matrix, run controls, status filters, markers, highlights).
135
- - **`FileList`** — a simple file list.
136
-
137
- Read the matching `example.ts` for each before using it — the examples are the
138
- source of truth for imports, ordering constraints, and wiring.
139
-
140
- ### Adding a built-in feature (the general pattern)
141
-
142
- Every manager-style built-in follows the same three steps. Example — adding clash
143
- detection (see `ClashesManager/example.ts` and `UIManager/src/clashes-panel/example.ts`):
144
-
145
- ```ts
146
- // 1. Import the built-in as a named export from @thatopen/services.
147
- import { PlatformClient, UIManager, ClashesManager } from "@thatopen/services";
148
-
149
- // 2. Register it by uuid in the SAME setup call as UIManager.
150
- const { components } = await client.setup<OBC.Components>(
151
- { OBC, OBF, BUI, THREE, FRAGS, MARKERJS },
152
- { uuid: UIManager.uuid },
153
- { uuid: ClashesManager.uuid },
154
- );
155
-
156
- // 3a. Init the manager. Do this BEFORE its panel mounts — the panel reads its
157
- // initial data in connectedCallback and only subscribes to changes afterward.
158
- await components.get(ClashesManager).init(client);
159
-
160
- // 3b. Mount the panel web component in a layout slot (UIManager registered it).
161
- app.elements = {
162
- // …existing elements…
163
- clashes: () => BUI.html`<top-clashes-panel></top-clashes-panel>`,
164
- };
165
- app.layouts = {
166
- // …existing layouts…
167
- Clashes: { icon: "mdi:vector-intersection", template: `"clashes viewer" 1fr / 22rem 1fr` },
168
- };
169
- ```
170
-
171
- The panel self-wires to its manager — you do not pass props or wire events by hand.
172
-
173
- ## Loading a BIM model
174
-
175
- ```ts
176
- const fragments = components.get(OBC.FragmentsManager);
177
-
178
- // From URL
179
- const buffer = await (await fetch("https://example.com/model.frag")).arrayBuffer();
180
- await fragments.core.load(buffer, { modelId: "my-model" });
181
-
182
- // From platform storage
183
- const fileBuffer = await (await client.downloadFile(fileId)).arrayBuffer();
184
- await fragments.core.load(fileBuffer, { modelId: "my-model" });
185
- ```
186
-
187
- (The scaffold's `<top-models-list>` panel already loads models the user picks, so you
188
- usually don't need to do this by hand.)
189
-
190
- ## PlatformClient API (commonly used in apps)
191
-
192
- ```ts
193
- const client = PlatformClient.fromPlatformContext();
194
- console.log(client.context.projectId);
195
-
196
- // Files / folders
197
- const files = await client.listFiles();
198
- const response = await client.downloadFile(fileId);
199
- await client.createFile({ file: blob, name: "model.ifc", versionTag: "v1" });
200
- await client.createFolder("My Folder");
201
-
202
- // Execute cloud components
203
- const { executionId } = await client.executeComponent(componentId, { param: "value" });
204
- client.onExecutionProgress(executionId, (data) => {
205
- // data.progressUpdate — progress %, data.messageUpdate — status
206
- });
207
-
208
- // Test against a local cloud component (thatopen local-server running in that project)
209
- client.localServerUrl = "http://localhost:4001";
210
- ```
211
-
212
- ## Configuration
213
-
214
- - `.thatopen` — local config (gitignored). Created by `npm run login`; also holds
215
- `beta: true` for beta projects and the `appId` after the first publish.
216
- - `vite.config.js` — builds the IIFE `dist/bundle.js`; for beta projects it aliases
217
- the `@thatopen/*` engine imports to their `@thatopen-platform/*-beta` packages.
1
+ # ThatOpen BIM App
2
+
3
+ This is a BIM (Building Information Modeling) app built for the That Open Platform.
4
+ It runs in the browser inside the platform's iframe and has access to a 3D viewer,
5
+ UI components, and the platform API.
6
+
7
+ > IMPORTANT for AI assistants: the authoritative, always-current reference for the
8
+ > platform rules, the built-in components, and how to wire each one is shipped
9
+ > inside the installed package. Read these before writing code:
10
+ >
11
+ > - `node_modules/@thatopen/services/resources/AGENTS.md` — platform rules + the
12
+ > full navigation table.
13
+ > - `node_modules/@thatopen/services/docs/builtin/paths.json` — the index of every
14
+ > built-in component, with a one-line description and the path to its example.
15
+ > - `node_modules/@thatopen/services/src/built-in/<Component>/example.ts` — a
16
+ > complete, copy-adaptable integration example per component.
17
+ >
18
+ > This README explains the app's shape and the general pattern. For the exact API
19
+ > of any built-in, trust `paths.json` + the example files over any list here.
20
+
21
+ ## How this app works
22
+
23
+ - **Entry point**: `src/main.ts` — runs as an IIFE when the platform loads the app.
24
+ - **Build output**: `dist/bundle.js` — a single IIFE file.
25
+ - **Platform context**: the platform injects the app's context (project id, access
26
+ token, API url). `PlatformClient.fromPlatformContext()` reads it for you.
27
+
28
+ ## Commands
29
+
30
+ ```bash
31
+ npm run dev # Start the dev server (esbuild watch + serve on :4000)
32
+ npm run build # Build dist/bundle.js
33
+ npm run login # Authenticate with the platform (saves token locally)
34
+ npm run publish # Publish to the platform
35
+ ```
36
+
37
+ ### Local development
38
+
39
+ Apps run inside the That Open Platform within a project, not as standalone websites.
40
+ To develop locally:
41
+
42
+ 1. Run `npm run dev` — watches source with esbuild and serves the bundle on port 4000.
43
+ 2. Open your project on the platform and click the debug button.
44
+ 3. Live reload is enabled — save a file to rebuild automatically.
45
+
46
+ **Important**: use `npm run dev` (it runs `thatopen serve` under the hood). Do NOT run
47
+ `vite` / `vite build --watch` directly for development — `thatopen serve` applies the
48
+ correct build settings (including the beta engine-library aliases for beta projects).
49
+
50
+ ## Key libraries
51
+
52
+ | Package | Import as | Purpose |
53
+ |---------|-----------|---------|
54
+ | `@thatopen/components` | `OBC` | BIM engine — components, fragments, worlds |
55
+ | `@thatopen/components-front` | `OBF` | Front-end BIM components (Highlighter, measurements, …) |
56
+ | `@thatopen/fragments` | `FRAGS` | Fragment geometry format |
57
+ | `@thatopen/ui` | `BUI` | UI web components (`<bim-panel>`, `<bim-grid>`, …) |
58
+ | `three` | `THREE` | 3D rendering engine |
59
+ | `@markerjs/markerjs3` | `MARKERJS` | Screenshot annotation |
60
+ | `@thatopen/services` | (named exports) | Platform API client (`PlatformClient`) + built-in components |
61
+
62
+ ```ts
63
+ import * as OBC from "@thatopen/components";
64
+ import * as OBF from "@thatopen/components-front";
65
+ import * as FRAGS from "@thatopen/fragments";
66
+ import * as BUI from "@thatopen/ui";
67
+ import * as THREE from "three";
68
+ import * as MARKERJS from "@markerjs/markerjs3";
69
+ import { PlatformClient, UIManager } from "@thatopen/services";
70
+ ```
71
+
72
+ ## Architecture
73
+
74
+ The app boots on the **`UIManager`** built-in. `UIManager` registers the platform's
75
+ web components — the app shell and viewport plus every panel — as custom elements you
76
+ place with plain HTML/`BUI.html`:
77
+
78
+ - `<top-app>` — the app shell: a CSS-grid layout system with a sidebar (activity bar)
79
+ for switching named layouts.
80
+ - `<top-viewer>` — the 3D viewport (pre-configured world: scene, camera, renderer,
81
+ fragments), with its own tools baked in.
82
+ - `<top-viewer-toolbar>` — the bottom viewer toolbar (visibility/inspect, clip, measure).
83
+ - Side panels — `<top-model-tree>`, `<top-properties-panel>`, `<top-models-list>`,
84
+ `<top-data-table-panel>`, `<top-objects-panel>`, `<top-settings-panel>`, … — each
85
+ self-wires from the contexts `<top-app>` provides (no `components` plumbing needed).
86
+
87
+ The scaffolded `src/main.ts` already sets this up. The shape is:
88
+
89
+ ```ts
90
+ const client = PlatformClient.fromPlatformContext();
91
+
92
+ // 1. Register the platform web components. UIManager MUST be in setup — it
93
+ // defines <top-app>, <top-viewer>, the panels, etc. before the DOM renders.
94
+ const { components } = await client.setup<OBC.Components>(
95
+ { OBC, OBF, BUI, THREE, FRAGS, MARKERJS },
96
+ { uuid: UIManager.uuid },
97
+ );
98
+ components.get(UIManager).init();
99
+
100
+ // 2. Build the shell: <top-app> with named element slots + named layouts.
101
+ const app = document.createElement("top-app") as any;
102
+ app.elements = {
103
+ viewer: () => BUI.html`<top-viewer></top-viewer>`,
104
+ tree: () => BUI.html`<top-model-tree></top-model-tree>`,
105
+ // …more panels…
106
+ };
107
+ app.layouts = {
108
+ Explorer: { icon: "mdi:file-tree", template: `"tree viewer" 1fr / 22rem 1fr` },
109
+ // …more layouts…
110
+ };
111
+ app.layout = "Explorer";
112
+ app.sidebar = true;
113
+ document.getElementById("that-open-app")?.appendChild(app);
114
+ ```
115
+
116
+ A layout `template` is CSS `grid-template` shorthand: `"areas" rows / columns`, where
117
+ each area name maps to a key in `app.elements`. Each layout with an `icon` becomes a
118
+ sidebar (activity-bar) button.
119
+
120
+ Built-ins are loaded from the platform at runtime **by uuid** through the `setup`
121
+ call. You import each one as a named export from `@thatopen/services` (a ready
122
+ `{ uuid }` stub with types), never by a deep/internal path.
123
+
124
+ ## Built-in components
125
+
126
+ The current, authoritative list lives in
127
+ `node_modules/@thatopen/services/docs/builtin/paths.json` (index) with a full example
128
+ per component under `node_modules/@thatopen/services/src/built-in/`. At a high level:
129
+
130
+ - **`UIManager`** — the shell + viewport + all `top-*` panels above (already wired by
131
+ the scaffold).
132
+ - **`CDEManager`** — the platform CDE: files, folders, versions, metadata.
133
+ - **`ClashesManager`** + `<top-clashes-panel>` — clash detection and the ready-made
134
+ clash review UI (detection matrix, run controls, status filters, markers, highlights).
135
+ - **`FileList`** — a simple file list.
136
+
137
+ Read the matching `example.ts` for each before using it — the examples are the
138
+ source of truth for imports, ordering constraints, and wiring.
139
+
140
+ ### Adding a built-in feature (the general pattern)
141
+
142
+ Every manager-style built-in follows the same three steps. Example — adding clash
143
+ detection (see `ClashesManager/example.ts` and `UIManager/src/clashes-panel/example.ts`):
144
+
145
+ ```ts
146
+ // 1. Import the built-in as a named export from @thatopen/services.
147
+ import { PlatformClient, UIManager, ClashesManager } from "@thatopen/services";
148
+
149
+ // 2. Register it by uuid in the SAME setup call as UIManager.
150
+ const { components } = await client.setup<OBC.Components>(
151
+ { OBC, OBF, BUI, THREE, FRAGS, MARKERJS },
152
+ { uuid: UIManager.uuid },
153
+ { uuid: ClashesManager.uuid },
154
+ );
155
+
156
+ // 3a. Init the manager. Do this BEFORE its panel mounts — the panel reads its
157
+ // initial data in connectedCallback and only subscribes to changes afterward.
158
+ await components.get(ClashesManager).init(client);
159
+
160
+ // 3b. Mount the panel web component in a layout slot (UIManager registered it).
161
+ app.elements = {
162
+ // …existing elements…
163
+ clashes: () => BUI.html`<top-clashes-panel></top-clashes-panel>`,
164
+ };
165
+ app.layouts = {
166
+ // …existing layouts…
167
+ Clashes: { icon: "mdi:vector-intersection", template: `"clashes viewer" 1fr / 22rem 1fr` },
168
+ };
169
+ ```
170
+
171
+ The panel self-wires to its manager — you do not pass props or wire events by hand.
172
+
173
+ ## Loading a BIM model
174
+
175
+ ```ts
176
+ const fragments = components.get(OBC.FragmentsManager);
177
+
178
+ // From URL
179
+ const buffer = await (await fetch("https://example.com/model.frag")).arrayBuffer();
180
+ await fragments.core.load(buffer, { modelId: "my-model" });
181
+
182
+ // From platform storage
183
+ const fileBuffer = await (await client.downloadFile(fileId)).arrayBuffer();
184
+ await fragments.core.load(fileBuffer, { modelId: "my-model" });
185
+ ```
186
+
187
+ (The scaffold's `<top-models-list>` panel already loads models the user picks, so you
188
+ usually don't need to do this by hand.)
189
+
190
+ ## PlatformClient API (commonly used in apps)
191
+
192
+ ```ts
193
+ const client = PlatformClient.fromPlatformContext();
194
+ console.log(client.context.projectId);
195
+
196
+ // Files / folders
197
+ const files = await client.listFiles();
198
+ const response = await client.downloadFile(fileId);
199
+ await client.createFile({ file: blob, name: "model.ifc", versionTag: "v1" });
200
+ await client.createFolder("My Folder");
201
+
202
+ // Execute cloud components
203
+ const { executionId } = await client.executeComponent(componentId, { param: "value" });
204
+ client.onExecutionProgress(executionId, (data) => {
205
+ // data.progressUpdate — progress %, data.messageUpdate — status
206
+ });
207
+
208
+ // Test against a local cloud component (thatopen local-server running in that project)
209
+ client.localServerUrl = "http://localhost:4001";
210
+ ```
211
+
212
+ ## Configuration
213
+
214
+ - `.thatopen` — local config (gitignored). Created by `npm run login`; also holds
215
+ `beta: true` for beta projects and the `appId` after the first publish.
216
+ - `vite.config.js` — builds the IIFE `dist/bundle.js`; for beta projects it aliases
217
+ the `@thatopen/*` engine imports to their `@thatopen-platform/*-beta` packages.