--- title: "Embedded UI Architecture Reference" slug: "embedded-ui-architecture-reference" tags: ["embedded-ui", "reference-guides"] status: "update" updated: 2026-10-13T18:18:38Z published: 2026-10-13T18:18:38Z canonical: "docs.unqork.io/embedded-ui-architecture-reference" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.unqork.io/llms.txt > Use this file to discover all available pages before exploring further. # Embedded UI Architecture Reference Embedded UI lets external web applications display Unqork modules on their own pages. To use it, a host page adds a single `<script>` tag from the Unqork server. That script registers a JavaScript API on `window.unqork`, creates a custom HTML element to hold the module, and starts the appropriate runtime (Centauri or Vega) inside a Shadow DOM boundary that keeps the module isolated from the host page's styles and scripts. This reference covers the system architecture, file responsibilities, initialization sequence, and internal class hierarchy for Embedded UI. ## Design Principles These principles shape every technical decision in Embedded UI. Understanding them helps you predict system behavior and choose the right embedding approach for your use case. | Principle | Implementation | | --- | --- | | Isolation | Shadow DOM prevents CSS bleed; navigation guards prevent URL hijacking. | | Runtime Transparency | Host developers call the same API regardless of which module runtime is used. | | Lazy Loading | Runtime scripts are loaded only when the first module of that type is mounted, reducing initial page load. | | Authentication Flexibility | Supports anonymous, SAML, OIDC, login form, and refer-string authentication methods. | | Minimal Host Impact | Requires a single `<script>` tag; no build-tool integration is needed in the host page. | ## Terminology The following terms appear throughout this reference. Review these definitions before reading the technical sections below. | Term | Meaning | | --- | --- | | Host Page | The external HTML page that embeds the Unqork module. | | Centauri | Unqork's Angular-based runtime, used for v1.x modules. | | Vega | Unqork's React-based runtime, used for v2.x modules. | | Module | A single Unqork form or UI unit, identified by a MongoDB ObjectId. | | Workflow | An ordered sequence of modules with navigation controls (Next, Previous, Save and Exit). | | Shadow DOM | A browser API that encapsulates DOM and CSS inside a private boundary, preventing styles from leaking in or out. | ## High-Level Component Diagram This diagram displays the main components and how they connect at a high level. The host page loads a single script that sets up the runtime and manages all communication between the host and the embedded module. ![Diagram](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/api_upload_20261013_181835_0d2253a8b8804ab19b52cc1f5936a066.svg?sv=2026-02-06&spr=https&st=2026-11-08T10%3A25%3A50Z&se=2026-11-08T11%3A25%3A50Z&sr=c&sp=r&sig=LxB%2BaN08ISZs6Ry5SXyhf2JjWOysL9zgbOltHmak9jc%3D) ## Request Flow — Centauri Module This sequence diagram traces the full loading and mounting flow for a Centauri module, from the host page's initial script request to the module rendering inside the Shadow DOM. ![Diagram](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/api_upload_20261013_181835_04d12b9b05fe4899b01c351101098a34.svg?sv=2026-02-06&spr=https&st=2026-11-08T10%3A25%3A50Z&se=2026-11-08T11%3A25%3A50Z&sr=c&sp=r&sig=LxB%2BaN08ISZs6Ry5SXyhf2JjWOysL9zgbOltHmak9jc%3D) ## Core File Map The following tables list every file involved in Embedded UI, grouped by role. Use this map to find the source of a specific behavior or to identify which file to modify for a given change. | File | Location | Purpose | | --- | --- | --- | | `index-js-express.njk` | `packages/unqork-server/views/` | Server-side template that injects `WINDOW_VARS` (environment variables and feature flags), then includes `scripts/embedded.js`. | | `embedded.js` | `packages/unqork-server/views/scripts/` | Entry-point script: defines `UnqorkRuntime`, `CentauriRuntime`, and `VegaRuntime`; registers all three on `window.unqork`. | | `spa-embed.js` | `packages/unqork-express/src/app/` | Core Centauri embed engine: creates the Shadow DOM, bootstraps Angular, enforces navigation guards, manages the template cache, and configures router states. | | `embed-loader.js` | `packages/unqork-express/src/app/` | Defines the `UnqorkCentauriElement` custom HTML element and wires up the `window.unqorkCentauri` API. | | `embed-utils.js` | `packages/unqork-express/src/app/` | Shared helpers: `isEmbeddedMode()`, `setEmbeddedMode()`, and `surfaceEmbedError()`. | | `index.route.js` | `packages/unqork-express/src/app/` | Defines Angular UI-Router states for embed mode: `embedDisplay` and `embedWorkflow*`. | ### Workflow-Specific Files | File | Purpose | | --- | --- | | `controllers/displayWorkflow.js` | The `DisplayWorkflow` controller handles workflow API calls, step navigation, and submission persistence. | | `services/WorkflowResponseReceivedHandler.js` | Processes workflow API responses and handles redirects and navigation state changes. | | `services/WorkflowUriResolver.js` | Resolves the URI for each workflow step. | | `services/WorkflowPreviousStateResolver.js` | A UI-Router resolve function that captures the previous state for back-navigation support. | ### Iframe Embed Files | File | Location | Purpose | | --- | --- | --- | | `EmbedDisplayController.js` | `src/app/controllers/` | Orchestrates the iframe-side embed: initializes security, messaging, API handlers, resize management, and event broadcasting. | | `embed-security.js` | `src/app/controllers/embed/` | Enforces security: rate limiting, HMAC signing, input sanitization, and origin validation. | | `embed-messaging.js` | `src/app/controllers/embed/` | Manages the postMessage protocol helpers and the initial handshake between host and iframe. | | `embed-api-handlers.js` | `src/app/controllers/embed/` | Handles API requests from the host: get and set data, validation, and form submission. | | `embed-resize.js` | `src/app/controllers/embed/` | Automatically adjusts the iframe height using ResizeObserver, MutationObserver, and a polling fallback. | | `embed-events.js` | `src/app/controllers/embed/` | Watches for module events and broadcasts them to the host page. | ### Test Files #### Unit and Integration Tests These files live in `/src/app/__tests__/` and run with Jest. | File | Type | Count | What it covers | | --- | --- | --- | --- | | `spa-embed.test.js` | Unit | ~30 | Angular mounting and unmounting, navigation guard URL interception, template cache decorator, UI-Router state definitions (`embedDisplay`, `embedWorkflow*`), `navigateToModule()` and `navigateToWorkflow()` routing, workflow priority when both `workflowPath` and `moduleId` are provided, Angular bootstrap error handling. | | `embed-loader.test.js` | Unit | ~20 | `window.unqorkCentauri` API surface (`mount()`, `destroy()`), `UnqorkCentauriElement` custom element registration, config and module data binding (`_config`, `_moduleId`, `_moduleData`), workflow mounting with `workflowPath` and `submissionId`, destroy and remount lifecycle. | | `embed.integration.test.js` | Integration | ~26 | Full mount flow from `initialize()` to Shadow DOM creation, runtime detection for Centauri (v1.x) and Vega (v2.x), fallback to Centauri on missing or failed version fetch, authentication state detection (401 handling), navigation guard event dispatch, workflow-always-Centauri enforcement, `unqork-workflow-mounted` event, error handling for network and 404 failures. | ## Initialization and Boot Sequence This section displays the step-by-step sequence that runs when Embedded UI loads. The flowchart covers everything from the initial script tag to the module mounting inside the host page. ![Diagram](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/api_upload_20261013_181835_e481a85d909f463c92ed676f7d477399.svg?sv=2026-02-06&spr=https&st=2026-11-08T10%3A25%3A50Z&se=2026-11-08T11%3A25%3A50Z&sr=c&sp=r&sig=LxB%2BaN08ISZs6Ry5SXyhf2JjWOysL9zgbOltHmak9jc%3D) ### Server-Side Rendering The Nunjucks template `index-js-express.njk` injects server-known values before the client-side JavaScript runs. The following variables configure the runtime to connect to the correct environment: | Variable | Source | Example | | --- | --- | --- | | `RUNTIME_VARS.runtimeId` | Query param or `'default'` | `'default'` | | `RUNTIME_VARS.hostUrl` | Computed from the incoming request | `'https://env.unqork.io'` | | `__UQENV__.REMOTE_ROOT` | Server configuration | `'https://d-env.unqork.io/'` | | `__UQENV__.CUSTOMER` | Server configuration | `'acme-corp'` | | `FEATURE_TOGGLES` | LaunchDarkly or environment configuration | `{ 'enable-unq-styles': true, ... }` | ### Class Hierarchy ``` window.unqork.runtimes.default  →  UnqorkRuntime    ├── ._centauriRuntime       →  CentauriRuntime  (created lazily)    │       └── ._centauriApi   →  window.unqorkCentauri  (set by embed-loader.js)    └── ._vegaRuntime           →  VegaRuntime      (created lazily)            └── ._runtimeApi    →  window.makeUnqorkApi()  (Vega SDK) ``` ## Runtime Detection When `mountModule({ moduleId })` is called, `UnqorkRuntime` fetches the module definition from `/fbu/form/{moduleId}` and inspects `settings.runtimeVersion` to decide which runtime to use: | `settings.runtimeVersion` | Selected Runtime | | --- | --- | | `"1.0.0"` or starts with `"1."` | Centauri | | `"2.0.0"` or starts with `"2."` | Vega | | Missing or undefined | Centauri (default) | | API error or 404 | Centauri (default) | Results are cached in `UnqorkRuntime._moduleRuntimeCache` (a `Map`), so repeat mounts of the same module skip the API call. The module definition fetched for detection is also passed to the internal runtime's `mountModule()`, avoiding a duplicate API request. ![Diagram](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/api_upload_20261013_181835_5b26cc6030ef4af8afc196eb1b3b7967.svg?sv=2026-02-06&spr=https&st=2026-11-08T10%3A25%3A50Z&se=2026-11-08T11%3A25%3A50Z&sr=c&sp=r&sig=LxB%2BaN08ISZs6Ry5SXyhf2JjWOysL9zgbOltHmak9jc%3D) ## Centauri Embedded — Three-Layer Architecture The Centauri embedded mode uses three JavaScript files, each with a distinct role. The table below displays how they stack and each layer's responsibilities. | File | Responsibilities | | --- | --- | | `embed-loader.js` | Defines `UnqorkCentauriElement` (an `HTMLElement` subclass), sets `window.unqorkCentauri`, and manages the custom element lifecycle. | | `spa-embed.js` | Core embed engine: `bootstrap()` sets up and bootstraps the Angular module; `mount()` runs the full mount flow (styles, bootstrap, state navigation); `unmount()` cleans up; enforces navigation guards and manages the template system. | | `index.route.js` | Defines UI-Router states (`embedDisplay`, `embedWorkflow*`) and provides inline templates for workflow states. | ### Angular States for Embed Mode Embed mode registers its own set of UI-Router states inside the Shadow DOM so the embedded module can navigate between forms and workflow steps without modifying the host page's URL or routing tree. The table below lists each state, its URL pattern, the controller it uses, and how its template is provided. | State Name | URL Pattern | Controller | Template | | --- | --- | --- | --- | | `home` | `/` | `HomeController` | `views/home.html` (empty in embed) | | `embedDisplay` | `/embed/display/:formId/:submissionId?/:submissionFormId?` | `EmbedDisplayController` | Inline: `<display-form-main ng-controller="displayForm">` | | `embedWorkflowStart` | `/embed/workflow/:workflowPath` | `DisplayWorkflow` | Inline workflow template | | `embedWorkflowPath` | `/embed/workflow/:workflowPath/:stepPath` | `DisplayWorkflow` | Inline workflow template (with params) | | `embedWorkflowStepSubmission` | `/embed/workflow/:workflowPath/:stepPath/submission/:submissionId` | `DisplayWorkflow` | Inline workflow template | | `embedWorkflowSubmission` | `/embed/workflow/:workflowPath/submission/:submissionId` | `DisplayWorkflow` | Inline workflow template | > [!NOTE] > Workflow states use inline `template` (not `templateUrl`) because the HTTP interceptor prefixes relative URLs with `hostUrl`, which would cause `$templateCache` key mismatches. ## Angular Services Decorated in Embed Mode In embed mode, Angular services are decorated and HTTP interceptors are registered to prevent the embedded module from interfering with the host page. The table below lists the key modifications and their purpose. | Service | Modification | Purpose | | --- | --- | --- | | `$browser` | `url()` no-op on SET | Prevents Angular from changing the host page's URL when the embedded module navigates internally. | | `$templateRequest` | Return from `EMBED_TEMPLATES`; surface errors on failure | Prevents the module from making HTTP requests for Angular templates; surfaces template errors to the host instead. | | `$exceptionHandler` | Delegate + `surfaceError()` | Catches Angular runtime exceptions and forwards them to the host page as embed error events. | | `$httpProvider` (interceptor) | Prefix relative URLs with `hostUrl`; `surfaceError()` on rejection | Prefixes relative URLs with `hostUrl` to redirect all relative API calls to the Unqork server; surfaces HTTP errors to the host. | ## Vega Embedded — Overview The Vega embedded is simpler because the Vega runtime API (`runtimeApi.js`) handles its own mounting and isolation. The host-facing API calls are identical to the Centauri path; the difference is internal. ![Diagram](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/api_upload_20261013_181835_bed5432254d346a1a308dce5a994817a.svg?sv=2026-02-06&spr=https&st=2026-11-08T10%3A25%3A50Z&se=2026-11-08T11%3A25%3A50Z&sr=c&sp=r&sig=LxB%2BaN08ISZs6Ry5SXyhf2JjWOysL9zgbOltHmak9jc%3D) | Aspect | Centauri | Vega | | --- | --- | --- | | Shadow DOM | Created by `embed-loader.js` | Managed internally by `runtimeApi` | | Angular | Bootstrapped manually by `spa-embed.js` | Not used | | Template system | Custom `$templateCache` with HTTP interception | React virtual DOM | | Navigation guards | `$browser` decorator suppresses URL changes | Not needed (no URL routing) | | Script loaded | `centauri-embed.js` | `runtimeApi.js` (loaded as a module type) | ## File Dependency Graph This diagram traces how each file depends on or loads another file. Use it to understand the relationship between the entry point script and the runtime-specific code. ![Diagram](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/api_upload_20261013_181835_b0ba961ae68145208027d64826612d33.svg?sv=2026-02-06&spr=https&st=2026-11-08T10%3A25%3A50Z&se=2026-11-08T11%3A25%3A50Z&sr=c&sp=r&sig=LxB%2BaN08ISZs6Ry5SXyhf2JjWOysL9zgbOltHmak9jc%3D) --- **Changelog** | Date | Change | | --- | --- | | 2026-06-09 | Editorial pass: rewrote introduction for accessibility, removed HR dividers between sections, fixed heading em dashes (colon substitution), fixed British spelling (sanitisation → sanitization), added why-descriptions to all sections lacking prose intros, expanded table descriptions for non-experts, fixed "through" → "using" in Iframe Embed Files, added See Also section with links to published paths. | | 2026-06-15 | Three-layer architecture table replaced with ASCII diagram; embedWorkflowSubmission URL pattern corrected; $httpProvider row updated; headings updated to em dash format. | | 2026-04-21 | Initial publication. | The UI (user interface) is a device's end-user interaction and communication point. It can include display screens, keyboards, and mouse. It is also how a user interacts with your application. JavaScript is an object-oriented computer programming language. It is most-commonly used for interactive effects in the browser. APIs (application programming interfaces) are a set of protocols and definitions developers use to build and integrate application software. APIs act as the connective tissue between products and services. HTML (Hyper Text Markup Language) is the standard markup language for for achieving font, color, graphic, and hyperlink effects when creating web pages. The Centauri (v 1.0.0) runtime is the first-generation foundation of the Unqork Designer Platform. Centauri provides Creators a codeless experience for developing applications. The Vega (v 2.0.0) runtime is the next-generation engine of the UDesigner platform. Vega uses cutting-edge technologies to improve the Creator and end-user experience. The Shadow DOM is a web standard that allows you to create encapsulated, hidden DOM subtrees for your web components. It provides a way to scope CSS styles and JavaScript behavior within a component, preventing them from leaking out and interfering with the rest of the page. The Document Object Model (DOM) is the data representation of objects that form the structure and content of a document on the web. The DOM represents the page. Cascading Style Sheets (CSS) is a style sheet language used for presenting how a HTML or XML document looks to end-users. A URL (uniform resource locator) is a unique identifier used to locate a resource on the internet. Also known as a web address. A runtime engine is software that runs on a computer to allow applications to execute. Security Assertion Markup Language (SAML) is a protocol that allows an identity provider (IdP) to send a user's credentials to a service provider (SP) to verify their identity and grant them access to a service. OIDC (OpenID Connect) is an identity authentication protocol that lets two applications share user information without exposing user credentials. A string is an object that represents a sequence of characters. Strings typically hold data represented in text form. AngularJS is a JavaScript framework added to an HTML page with a