---
title: "Install and show your first UI"
description: "Quartz UI 0.57.0-dev: Install and show your first UI. Source-reviewed guidance, usage and limitations."
status: approved
visibility: public
sourceRevision: fe5b709ec900e282b50e58b819a25041945005f9
reviewedAt: 2026-09-24
---

# Install and show your first UI

> **0.57.0-dev · beta source documentation.** Native, Blueprint, Editor and rendering examples are source-reviewed, not executed in Unreal during this scan. See [validation and limits](https://betterbuilt.games/docs/quartz-ui/evidence).

Use a C++ host project compatible with Unreal 5.8 on Win64. The plugin repository has no `.uproject`, build target, or bundled host game. Install the appropriate Unreal C++ toolchain for the host. The descriptor contains client runtime, optional GAS, editor, and editor-only test modules; dedicated servers must not depend unconditionally on client modules.

## Install the source

Obtain the authorized source repository URL through your existing access. Substitute it below; these instructions do not grant access. From the consuming project's root:

```powershell
git submodule add <AUTHORIZED_QUARTZUI_REPOSITORY_URL> Plugins/QuartzUI
git submodule update --init --recursive
git -C Plugins/QuartzUI checkout fe5b709ec900e282b50e58b819a25041945005f9
```

Merge a `{"Name":"QuartzUI","Enabled":true}` entry into the existing `.uproject` Plugins array. Preserve other entries. Regenerate project files and build the host Editor target. Source uses Epic's `WebBrowser` module; the separate `WebBrowserWidget` runtime plugin is not required by the descriptor. See the discrepancy in [gaps](https://betterbuilt.games/docs/quartz-ui/limits).

Native modules that expose QuartzUI types in public headers add `QuartzUIRuntime` to `PublicDependencyModuleNames`; otherwise use private dependencies. Keep `QuartzUIEditor` dependencies in editor modules. Include individual headers such as `QuartzUIBlueprintLibrary.h`, not private implementation files.

## Create the project app

Create a Data Asset of class **QuartzUI App Asset** (use the generic Data Asset picker if no dedicated entry appears). Name it `DA_GameUI`. Set its Definition:

| Field | Value for this tutorial |
|---|---|
| App Id | `gameui` |
| Resource Owner | `Project` |
| Packaged Root | `Apps/gameui` |
| Entry Page | `index.html` |

These files belong at `<Project>/Content/QuartzUI/Apps/gameui`. `mvp` is a reserved compatibility fixture ID. A native app asset starts with fixture defaults; explicitly change ownership and ID for production.

Under **Project Settings > Plugins > QuartzUI**, choose `DA_GameUI` as Default App. Keep Startup Policy `Manual` for this walkthrough. Other settings supply frame rate, transparency, input, localization, fallback, resource roots, and budgets. App-specific presentation overrides apply only when their corresponding override switches are enabled. Save the asset and project settings.

## Prepare the frontend identity

Create a project-owned frontend source directory. Copy `Resources/Client/quartzui.mjs` into it (or use a build-time alias), retaining its source license. Generate the selected app's TypeScript:

```powershell
& '<UE_ROOT>/Engine/Binaries/Win64/UnrealEditor-Cmd.exe' `
  '<HOST_PROJECT>.uproject' -run=QuartzUIContract -App=gameui `
  '-Output=<PROJECT>/QuartzUI/Generated/gameui.contract.ts' -unattended -nop4
```

Compile that generated module with the frontend. Its exported `QUARTZUI_CONTRACT_HASH` and `QUARTZUI_CONTRACT_VERSION` identify exactly the app's registered contracts and providers. Do not copy a demo hash once the app has its own schema.

This small framework-neutral smoke page deliberately needs no npm installation. For a React project, keep the same client singleton and use the [React pattern](https://betterbuilt.games/docs/quartz-ui/gameplay#react-components).

```html
<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><title>Game UI</title></head>
<body>
  <p id="status">Connecting to Unreal...</p>
  <p>Ammo: <output id="ammo">waiting</output></p>
  <script type="module" src="./app.mjs"></script>
</body>
</html>
```

```js
// app.mjs: generated module must be compiled into this app, at this path.
import { QuartzUIClient } from './quartzui.mjs';
import { QUARTZUI_CONTRACT_HASH, QUARTZUI_CONTRACT_VERSION }
  from './generated/gameui.contract.js';

const status = document.querySelector('#status');
const ammo = document.querySelector('#ammo');
const client = new QuartzUIClient({
  contractHash: QUARTZUI_CONTRACT_HASH,
  contractVersion: QUARTZUI_CONTRACT_VERSION,
  onError: error => { status.textContent = error.code ?? error.message; },
});
const unsubscribe = client.subscribeState('hud.ammo', value => {
  // The scalar native facade wraps the value in an object.
  if (Number.isInteger(value.value)) ammo.textContent = String(value.value);
});
try {
  await client.ping();
  status.textContent = 'Connected to Unreal';
} catch (error) {
  status.textContent = error.code ?? error.message;
}
window.addEventListener('pagehide', () => { unsubscribe(); client.dispose(); }, { once: true });
```

Build/copy the HTML, compiled JS, and transport to the app root. All runtime imports must resolve within compiled output. A plain desktop browser has no Unreal gateway and should report `client.unavailable`; that is not a plugin test failure.

The frontend build must also emit `quartzui.build.manifest` with exactly six fields: `schemaVersion: 1`, `appId: "gameui"`, `resourceOwner: "project"`, `entryPage: "index.html"`, `contractFingerprint`, and `localizationFingerprint`. The fingerprints come from the selected generated contract and configured localization authority. [Packaging](https://betterbuilt.games/docs/quartz-ui/tools-shipping#build-metadata) explains how to compute them, including the minimal no-localization case. Do not name this file `.json`.

## Start and verify

In the local PlayerController Blueprint BeginPlay, call **Start UI Shell**, passing that controller, then **Set UI Integer**, name `hud.ammo`, value `30`, same controller. The equivalent C++ fragment is:

```cpp
#include "QuartzUIBlueprintLibrary.h"

// In a local APlayerController method; inspect false/null in production code.
if (ULocalPlayer* Player = GetLocalPlayer())
{
    if (FQuartzUI::StartShell(Player))
    {
        const bool bAccepted = FQuartzUI::SetIntegerValue(Player, TEXT("hud.ammo"), 30);
        ensure(bAccepted);
    }
}
```

Press Play. Expected: the page displays “Connected to Unreal” and ammo `30`. Ready requires both document load and a matching contract handshake. **Get UI Failure** reports why startup or loading failed. **Retry UI** retries only the supported bounded failure path; it cannot repair a stale frontend contract.

Alternative ownership: set GameMode HUD Class to `AQuartzUIHUD`, add `UQuartzUIShellComponent` to an existing HUD/controller, or enable Automatic startup. All target the same canonical shell. Do not make a separate UMG browser for this tutorial.

## Lifetime and mistakes

The GameInstance subsystem owns the shell, so HUD recreation or map travel does not intentionally close it. Call **Stop UI Shell** for an intentional close; player removal also cleans it up. Pass exact local players in split screen. An omitted controller works only when exactly one local player can be resolved.

Most blank-page failures come from an incorrect packaged path, a missing compiled import, stale fingerprints, a missing Default App, or a failed native mount. Diagnose those before adding delays or recreating the shell every frame. Run **Tools > Quartz UI > Advanced > Audit QuartzUI Project Apps** before packaging.

This walkthrough is source-reviewed, not PIE-executed in this scan. Pinned installation source (source: `Documentation/Installation.md`), app definition (source: `Source/QuartzUIRuntime/Public/QuartzUIApp.h`), client (source: `Resources/Client/quartzui.mjs`).

Canonical HTML: https://betterbuilt.games/docs/quartz-ui/first-ui
