Documentation Index
Fetch the complete documentation index at: https://v5.rpgjs.dev/llms.txt
Use this file to discover all available pages before exploring further.
Prebuilt GUI Contracts
RPGJS prebuilt GUIs are regular GUI entries registered with fixed IDs. You can replace their visual implementation with your own CanvasEngine component by registering a GUI with the same ID.
The server API stays the same. For example, player.showText() still opens rpg-dialog, but your component receives the dialog data and decides how to render it.
Register a Replacement
Create a .ce file and register it with the prebuilt ID you want to replace:
import { provideClientModules } from '@rpgjs/client'
import { PrebuiltGui } from '@rpgjs/common'
import MyDialog from './gui/my-dialog.ce'
export default {
providers: [
provideClientModules([
{
gui: [
{
id: PrebuiltGui.Dialog,
component: MyDialog,
},
],
},
]),
],
}
The last component registered for an ID wins. A CanvasEngine replacement removes any Vue entry with the same ID, and a Vue replacement removes the built-in CanvasEngine component. This page focuses on CanvasEngine .ce replacements; for Vue-specific examples, see Vue.js integration.
Component Interface
CanvasEngine GUI components receive:
| Prop | Description |
|---|
data | Signal containing the object sent by the server. Read it with data(). |
onFinish(value?) | Closes the GUI and resolves the server-side promise when the GUI was opened with waitingAction. |
onInteraction(name, payload?) | Sends an action to the server without closing the GUI. |
For example, this CanvasEngine component can replace the built-in dialog box:
<DOMContainer width="100%" height="100%">
<div class="my-dialog" data-position={position()}>
@if (speaker()) {
<strong>{speaker()}</strong>
}
<p>{message()}</p>
@if (choices().length) {
<div class="choices">
@for ((choice, index) of choices()) {
<button click={selectChoice(index)}>
{choice.text}
</button>
}
</div>
}
@else {
<button click={continueDialog()}>Continue</button>
}
</div>
</DOMContainer>
<script>
import { computed } from "canvasengine";
const { data, onFinish } = defineProps();
const message = computed(() => data().message || "");
const choices = computed(() => data().choices || []);
const speaker = computed(() => data().speaker || "");
const position = computed(() => data().position || "bottom");
function selectChoice(index) {
return function() {
onFinish(index);
};
}
function continueDialog() {
return function() {
onFinish();
};
}
</script>
Use onFinish() when the server is waiting for a final answer, such as a dialog choice. Use onInteraction() for actions that should keep the GUI open, such as buying an item or equipping gear.
Dialog Box
| Contract | Value |
|---|
| ID | PrebuiltGui.Dialog / rpg-dialog |
| Server APIs | player.showText(), player.showChoices() |
| Close with | onFinish(index?) |
Data:
| Field | Type | Description |
|---|
message | string | Text to display. |
choices | { text: string }[] | Choice labels. The original server-side value is not sent to the client. |
position | 'top', 'middle', or 'bottom' | Dialog placement. Defaults to bottom. |
fullWidth | boolean | Whether the dialog should use the full screen width. |
autoClose | boolean | Whether the dialog may close automatically. |
typewriterEffect | boolean | Whether the text should reveal progressively. |
speaker | string | Speaker label. |
face | { id: string; expression?: string } | Faceset spritesheet ID and expression. |
To return a choice, call onFinish(index) where index is the selected choice index. For text without choices, call onFinish() when the player dismisses the dialog.
CanvasEngine example:
<DOMContainer width="100%" height="100%">
<div class="dialog">
<p>{data().message}</p>
@for ((choice, index) of data().choices || []) {
<button click={selectChoice(index)}>{choice.text}</button>
}
@if (!(data().choices || []).length) {
<button click={closeText()}>Continue</button>
}
</div>
</DOMContainer>
<script>
const { data, onFinish } = defineProps();
function selectChoice(index) {
return function() {
onFinish(index);
};
}
function closeText() {
return function() {
onFinish();
};
}
</script>
Main Menu
| Contract | Value |
|---|
| ID | PrebuiltGui.MainMenu / rpg-main-menu |
| Server API | player.callMainMenu(options) |
| Close with | onInteraction('exit') or onFinish() |
Data:
| Field | Type | Description |
|---|
menus | { id; label; disabled? }[] | Menu entries. Default IDs are items, skills, equip, options, save, exit. |
items | MenuItem[] | Inventory entries with id, name, description, quantity, icon, stats, type, usable, equipped. |
equips | MenuItem[] | Inventory entries whose type is weapon or armor. |
skills | { id; name; description; spCost }[] | Player skills. |
saveLoad | object | Save overlay data, usually { mode: 'save', canSave, showAutoSlot, autoSlotIndex, autoSlotLabel }. |
playerStats | object | Current stats such as atk, pdef, sdef, str, dex, int, agi, maxHp, maxSp. |
expForNextlevel | number | EXP target for the next level. |
Interactions:
| Interaction | Payload | Server behavior |
|---|
useItem | { id } | Calls player.useItem(id) and refreshes menu data. |
equipItem | { id, equip } | Calls player.equip(id, equip) and refreshes menu data. |
openSave | none | Closes the main menu and opens rpg-save in save mode. |
exit | none | Closes the menu and resolves with 'exit'. |
The built-in client also applies optimistic updates for useItem and equipItem. Custom Vue and CanvasEngine replacements can use the same interaction names and still benefit from those reducers.
Shop
| Contract | Value |
|---|
| ID | PrebuiltGui.Shop / rpg-shop |
| Server API | player.callShop(options) |
| Close with | onFinish() |
Data:
| Field | Type | Description |
|---|
items | ShopItem[] | Items available to buy. |
sellItems | ShopItem[] | Player inventory items available to sell. |
playerParams | object | Current player stats used to compare item modifiers. |
message | string | Merchant message. |
face | { id: string; expression?: string } | Merchant faceset. |
ShopItem includes id, name, description, price, icon, type, optional stats, optional quantity, and equipped.
Interactions:
| Interaction | Payload | Server behavior |
|---|
buyItem | { id, nb } | Calls player.buyItem(id, nb) and refreshes shop data. |
sellItem | { id, nb } | Adds gold, removes inventory items, and refreshes shop data. |
Save and Load
| Contract | Value |
|---|
| ID | PrebuiltGui.Save / rpg-save |
| Server APIs | player.showSave(), player.showLoad(), player.showSaveLoad() |
| Close with | onFinish(index?) |
Data:
| Field | Type | Description | |
|---|
slots | `(SaveSlot | null)[]` | Save metadata without the snapshot field. Empty slots are null. |
mode | 'save' or 'load' | Selects save or load behavior. | |
showAutoSlot | boolean | Whether to display an auto-save entry. | |
autoSlotIndex | number | Slot index used by the auto-save entry. | |
autoSlotLabel | string | Label for the auto-save entry. | |
Server interactions:
| Interaction | Payload | Server behavior |
|---|
save | { index } | Saves into the slot and closes with the selected index. |
load | { index } | Loads the slot and closes with the selected index. |
select | { index } | Alias handled according to the current mode. |
The built-in save-load.ce also uses SaveClientService directly for local save/load UI flows. A replacement can use either the server interactions above or its own client service flow, depending on the game architecture.
Title Screen
| Contract | Value |
|---|
| ID | PrebuiltGui.TitleScreen / rpg-title-screen |
| Server API | player.gui('rpg-title-screen').open(options) when used from the server |
| Close with | onInteraction('select', selection) or local hide logic |
Data:
| Field | Type | Description |
|---|
entries | { id; label; disabled? }[] | Selectable actions. Defaults to start and load. |
title | string | Main title. |
subtitle | string | Subtitle. |
version | string | Version label. |
showPressStart | boolean | Option reserved by the server contract. |
saveLoad | object | Data passed to rpg-save when using local load behavior. |
localActions | boolean | If true, built-in title actions hide the title or open save/load locally. |
Interaction:
| Interaction | Payload |
|---|
select | { id, index, entry } |
Game Over
| Contract | Value |
|---|
| ID | PrebuiltGui.Gameover / rpg-gameover |
| Server API | player.callGameover(options) |
| Close with | onInteraction('select', selection) or local hide logic |
Data:
| Field | Type | Description |
|---|
entries | { id; label; disabled? }[] | Selectable actions. Defaults to title and load. |
title | string | Main title. |
subtitle | string | Subtitle. |
saveLoad | object | Data passed to rpg-save when using local load behavior. |
localActions | boolean | If true, built-in actions display the title screen or save/load locally. |
Interaction:
| Interaction | Payload |
|---|
select | { id, index, entry } |
HUD and Notifications
HudComponent and NotificationComponent are also GUI components, but they are less driven by a server payload than the modal GUIs above.
HUD data:
| Field | Type | Description |
|---|
faceset | { id: string; expression?: string } | Optional face displayed next to player status. |
The HUD reads the current player from the client engine for hp, sp, max values, and level.
Notifications use PrebuiltGui.Notification / rpg-notification, but the built-in component reads engine.notificationManager.stack() instead of a direct data payload. Custom notification UIs should use the same notification manager if they need the existing player.showNotification() behavior.