Canvas-rendered UI engine for game UI. Windows, buttons, panels, and labels skinned with 9-slice sprite assets.
npm install
npm run dev # launches the demo Vite SPAThe demo opens in a canvas ui-engine HUD showcase. The legacy React HUD now
lives in examples/react-reference and can be served standalone with
npm run dev:react-reference.
A second standalone example, Iter Belli (a fully interactive Roman
campaign HUD rendered through the canvas engine), lives in
examples/iter-belli:
npm install
npm run dev:iter-belli # http://localhost:5175 by default
npm run build:iter-belli # production build
npm run test:iter-belli-state # pure state-helper unit testsIter Belli consumes the dedicated iter_belli_* asset pack exported through
@ui-engine/theme-roman-spqr: its own header banners, mission banner,
parchment stat tiles, location/itinerary/log panel frames, 4 decision card
frames, 2 long action buttons, status icons, action icons, decision-effect
icons, route nodes, and log ornaments.
import { Engine, Window, Button, Label, StackContainer, preloadAssets } from '@ui-engine/core';
const canvas = document.querySelector('canvas')!;
const engine = new Engine(canvas);
const win = new Window({ x: 100, y: 100, width: 320, height: 240, title: 'Settings' });
const stack = new StackContainer({ direction: 'vertical', gap: 8, padding: 12 });
stack.add(new Label({ text: 'Volume' }));
stack.add(new Button({ text: 'OK', onClick: () => win.close() }));
win.body.add(stack);
engine.root.add(win);
engine.start();Use preloadAssets before starting the engine when your theme or widgets use
image-backed skins. It accepts image URLs, 9-slice definitions, skins, themes,
nested plain asset maps, or arrays that mix those shapes.
import { Engine, preloadAssets } from '@ui-engine/core';
import { romanSpqrTheme } from '@ui-engine/theme-roman-spqr';
const engine = new Engine(canvas, { theme: romanSpqrTheme });
await preloadAssets(romanSpqrTheme);
engine.start();Nested asset packs can be passed directly without flattening them by hand:
const hudAssets = {
icons: {
soldiers: '/hud/icon-soldiers.png',
morale: '/hud/icon-morale.png',
},
chrome: {
banner: '/hud/banner-mission.png',
watermark: '/hud/watermark-spqr.png',
},
};
await preloadAssets([romanSpqrTheme, hudAssets]);packages/core- the@ui-engine/corelibrary (built withtsc, ESM + types)packages/primitives- generic interactive widgets (Scroll,Tooltip,Modal,ProgressBar, plus stub gameplay primitives)packages/genre-turn-based- turn-based campaign widgets (MissionBanner,RoutePath,DecisionCardGrid,ResourceLedger,EventLogPanel)packages/theme-roman-spqr- Roman SPQR theme + sliced asset packpackages/knowledge-@ui-engine/knowledge: records, playbooks, skill drafts +ui-engine-knowledgeCLIpackages/prompts-@ui-engine/prompts: per-asset prompt registry + lineage manifests +ui-engine-promptsCLIpackages/cli-@ui-engine/cli: unifiedui-enginebin that dispatches to the per-package CLIsdemo- Vite SPA showcase that renders the canvas HUD via@ui-engine/coreexamples/react-reference- standalone Vite SPA with the legacy React HUD
After npm install, all workspace tooling is available behind a single bin:
npx ui-engine --help # top-level overview
npx ui-engine knowledge --help # knowledge subcommands
npx ui-engine knowledge retrieve "chroma key removal" # semantic search
npx ui-engine prompts lint # validate prompts + lineage
npx ui-engine assets inspect # read-only asset preflight
npx ui-engine widgets scaffold UnitPortrait --in primitives # scaffold a new widgetThe npm run * scripts below are convenience wrappers around the same
ui-engine <namespace> <subcommand> invocations. See
packages/cli/README.md for the full reference.
Prompts for ChatGPT Images 2 live in the @ui-engine/prompts registry,
one file per asset variant under packages/prompts/registry/<asset-type>/.
The shared style/constraints block lives at
packages/prompts/registry/shared/style-and-constraints.md. Each generated
PNG (and each derived/sliced PNG) carries a JSON lineage entry under
packages/prompts/lineage/.
Generated source images stay in packages/theme-roman-spqr/assets/*_generated_*.png.
Runtime sprites are derived from those sources by scripts under
scripts/hud-assets/, so do not hand-edit consumed PNGs.
npm run assets:inspect
npm run assets:slice:all
npm run build
npm run devnpm run prompts:new -- banner banner-event-v1 # scaffold a new prompt
npm run prompts:lint # validate registry + lineage
npm run prompts:lineage -- packages/theme-roman-spqr/assets/banner_*.pngRun assets:inspect before the mutating slicers when you want a read-only
preflight. It reports missing generated sources, detected component counts,
image dimensions, alpha mode, and chroma-key cleanup readiness without
rewriting any runtime PNGs.
ui-engine treats reusable asset and UI knowledge as project source, not only
as chat memory. Records, playbooks, and skill drafts live in
packages/knowledge/ (the @ui-engine/knowledge package). The
ui-engine-knowledge CLI validates, generates, indexes, and retrieves entries
from the corpus.
npm run knowledge:new -- mission-banner-safe-zone # create a record stub
npm run knowledge:check # validate schema + cross-refs
npm run knowledge:index # build the embeddings cache
npm run knowledge:retrieve -- "chroma key removal" # semantic search top-K
npm run knowledge:export-skills # stage skill drafts to .tmp/Run knowledge:check after changing records, playbooks, or skill drafts. Run
knowledge:index after editing record bodies — it regenerates the local
embeddings cache (packages/knowledge/.knowledge-index/embeddings.json) used
by knowledge:retrieve. The cache is gitignored.
See docs/knowledge-workflow.md for the full
schema (including the tags, applies_to_genres, applies_to_themes,
applies_to_packages fields), tag vocabulary, and CLI reference.