# Architecture This document describes how the three packages in Creator Hub connect and communicate at runtime. For per-package details, see each package's own README. For setup instructions, see the [root README](../README.md). ## Bird's eye view Creator Hub is a desktop application for building 3D scenes in [Decentraland](https://decentraland.org/). The codebase is a monorepo with three packages that form a linear dependency chain: ``` asset-packs ──▶ inspector ──▶ creator-hub ``` Each package is independently publishable to npm. `creator-hub` consumes the others as dependencies, but `inspector` and `asset-packs` can also run standalone. ``` ┌──────────────────────────────────────────────────────────┐ │ Creator Hub (Electron) │ │ │ │ ┌──────────────┐ IPC ┌───────────┐ contextBridge │ │ │ Main │◄──────►│ Preload │◄────────────────┐│ │ │ (Node.js) │ │ (Bridge) │ ││ │ └──────┬───────┘ └───────────┘ ││ │ │ ││ │ │ HTTP (localhost) ││ │ ▼ ││ │ ┌──────────────────────────────────────────────────┐ ││ │ │ Inspector (iframe) │ ││ │ │ ┌──────────┐ ┌──────────┐ ┌────────────────┐ │ ││ │ │ │Babylon.js│ │ Redux │ │ Data Layer │──┼──┘│ │ │ │ Engine │ │ + Saga │ │ (Proto / RPC) │ │ │ │ │ └──────────┘ └──────────┘ └────────────────┘ │ │ │ └──────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────┐ ┌─────────────┐ │ │ │ Renderer │ │ Asset Packs │ (runtime logic │ │ │ (React SPA) │ │ (SDK7 lib) │ loaded into scenes) │ │ └──────────────┘ └─────────────┘ │ └──────────────────────────────────────────────────────────┘ ``` ## Architecture invariants These are non-obvious design constraints that hold across the codebase. Violating them will break things in ways that aren't immediately apparent. 1. **Renderer never imports `electron` or Node.js modules directly.** All system access goes through the preload bridge (`preload/src/services/`). This boundary is enforced by Electron's context isolation and the Vite build configuration. 2. **The Inspector is transport-agnostic at the data layer.** It communicates exclusively through the `DataService` protocol (`data-layer.proto`), regardless of whether the backing storage is local files, an iframe bridge, or a remote WebSocket server. This means the Inspector can run in any context that implements the `DataService` RPC contract. 3. **Asset packs are self-contained.** They define their own component schemas and runtime systems using only the `@dcl/ecs` API. They must work with any Inspector version that supports the same SDK version. ## Communication patterns A running Creator Hub instance uses five distinct communication channels: ``` ┌───────────────────────────────────────────────────────────┐ │ Creator Hub Process │ │ │ │ ┌─────────┐ Electron IPC ┌──────────┐ │ │ │ Main │◄───────────────►│ Preload │ │ │ │ Process │ │ │ │ │ └────┬────┘ └─────┬────┘ │ │ │ │ contextBridge │ │ │ ▼ │ │ │ ┌──────────┐ │ │ │ │ Renderer │ │ │ │ │ (React) │ │ │ │ └────┬─────┘ │ │ │ │ │ │ │ HTTP │ postMessage │ │ │ (localhost:PORT) │ (MessageTransport) │ │ │ ▼ │ │ │ ┌──────────────────────┐ │ │ └─────────────────────►│ Inspector │ │ │ serves static files │ (iframe, Babylon.js)│ │ │ └──────────────────────┘ │ │ │ │ │ │ Asset Packs CDN ◄─── S3 bucket (binary assets) │ └───────────────────────────────────────────────────────────┘ ``` ### Electron IPC (creator-hub internal) The renderer communicates with the main process through Electron's `ipcRenderer.invoke` / `ipcMain.handle` pattern. The preload script wraps every call in a typed function. Channels are namespaced by domain: `electron.*`, `updater.*`, `inspector.*`, `cli.*`, `config.*`, `bin.*`, `code.*`, `analytics.*`, and `npm.*`. The type-safe IPC contract is defined in `shared/types/ipc.ts`. Both the main process handler registration (`main/src/modules/handle.ts`) and the preload invoke wrapper (`preload/src/services/ipc.ts`) use this shared type to ensure channel names and parameter types stay in sync at compile time. ### IFrame / postMessage (creator-hub to inspector) The Creator Hub's `EditorPage` component renders the Inspector in an `