SDK Reference

The @grids/overlay-sdk package provides a typed bridge between overlay UIs (React apps running in CEF) and the UE5 game engine.

Installation

npm install @grids/overlay-sdk

Quick Start

import { grids } from '@grids/overlay-sdk';

grids.on('notification:show', (data) => {
  console.log(data.title);
});

grids.send('asset-browser:spawn', { assetId: '123' });

API

grids.on(event, callback)

Listen for an event from the game engine. Returns an unsubscribe function.

const unsub = grids.on('context-menu:open', (data) => {
  // data is typed as ContextMenuOpenPayload
});

// Later: stop listening
unsub();

grids.send(event, data)

Send a message to the game engine.

grids.send('context-menu:select', { actionId: 'delete' });

grids.requestFocus()

Request input focus — the overlay becomes interactive and receives mouse/keyboard input. Game input continues (passthrough mode).

grids.releaseFocus()

Release input focus back to the game. The overlay becomes non-interactive (click-through).

grids.captureInput()

Capture all input exclusively — the overlay receives all keyboard and mouse input, and game input is blocked. Use this for modal overlays with text fields, search boxes, or any UI where typing WASD shouldn't move the character.

// When opening a modal overlay
grids.captureInput();

// The overlay now has exclusive input — typing won't move the player

grids.releaseInput()

Release exclusive input capture. Game input is restored. Call this when closing a modal overlay or when the user is done with text input.

// When closing the modal
grids.releaseInput();
grids.close();

grids.close()

Request the game to close this overlay. For persistent (preloaded) overlays, this hides the overlay instead of destroying it — the JS context stays alive and can continue receiving events. For ephemeral overlays, this fully destroys the overlay.

grids.isDevMode

Boolean indicating whether the SDK is running outside UE5 (in a browser for development). When true, a devtools panel is rendered for simulating events.

grids.devSend(event, data)

Only available in dev mode. Simulates a message from the game engine by dispatching a grids:message CustomEvent.

Event Map

All known events and their payload types:

EventDirectionPayload
context-menu:openGame → OverlayContextMenuOpenPayload
context-menu:selectOverlay → Game{ actionId: string }
context-menu:dismissOverlay → Game{}
asset-browser:initGame → OverlayAssetBrowserInitPayload
asset-browser:spawnOverlay → Game{ assetId: string }
asset-browser:closeOverlay → Game{}
notification:showGame → OverlayNotificationPayload
notification:dismissGame → Overlay{ id: string }
zone-loading:startGame → OverlayZoneLoadingStartPayload
zone-loading:progressGame → OverlayZoneLoadingProgressPayload
zone-loading:logGame → OverlayZoneLoadingLogPayload
zone-loading:errorGame → OverlayZoneLoadingErrorPayload
zone-loading:completeGame → OverlayZoneLoadingCompletePayload
zone-loading:retryOverlay → Game{}
zone-loading:cancelOverlay → Game{}

Custom events can use any string key — the map above defines the built-in typed events.

Type Definitions

NotificationPayload

interface NotificationPayload {
  id: string;
  type: 'info' | 'success' | 'warning' | 'error';
  title: string;
  message?: string;
  duration?: number; // ms, default 4000
}

ContextMenuOpenPayload

interface ContextMenuOpenPayload {
  displayName: string;
  screenX: number;
  screenY: number;
  items: ContextMenuItem[];
}

ContextMenuItem

interface ContextMenuItem {
  actionId: string;
  label: string;
  icon: string;
  enabled: boolean;
  destructive: boolean;
}

AssetBrowserInitPayload

interface AssetBrowserInitPayload {
  assets: AssetManifest[];
  playerId: string;
  playerName: string;
}

AssetManifest

interface AssetManifest {
  id: string;
  type: 'texture' | 'audio' | 'video' | 'model' | 'script';
  name: string;
  thumbUrl: string;
  dataUrl: string;
}

Zone Loading Types

ZoneLoadingStartPayload

interface ZoneLoadingStartPayload {
  zoneId: string;
  zoneName: string;
  description?: string;
  backgroundUrl?: string;
  ownerName?: string;
  sizeTier?: string;
  config?: Record<string, unknown>;
}

ZoneLoadingProgressPayload

type ZoneLoadingPhase =
  | 'connecting' | 'authenticating' | 'downloading'
  | 'loading' | 'spawning' | 'ready' | 'error';

interface ZoneLoadingProgressPayload {
  phase: ZoneLoadingPhase;
  message: string;
  progress: number; // 0-100, or -1 for indeterminate
  assets?: ZoneLoadingAsset[];
}

ZoneLoadingAsset

interface ZoneLoadingAsset {
  id: string;
  name: string;
  bytesLoaded: number;
  bytesTotal: number; // -1 if unknown
}

ZoneLoadingLogPayload

interface ZoneLoadingLogPayload {
  message: string;
  level: 'info' | 'warn' | 'error' | 'success';
}

ZoneLoadingErrorPayload

interface ZoneLoadingErrorPayload {
  message: string;
  canRetry: boolean;
}

ZoneLoadingCompletePayload

interface ZoneLoadingCompletePayload {
  zoneId: string;
  zoneName: string;
}

Dev Mode

When the SDK detects no UE5 bridge (window.ue.grids is undefined), it enters dev mode:

This lets you develop overlays entirely in a browser with npm run dev.