Skip to main content

Chat module

@rpgjs/chat is an optional RPGJS v5 module with a server-authoritative message flow:
  1. The client submits text and a requested channel.
  2. The server normalizes and validates the text, applies rate limits and moderation, and reconstructs the author and timestamp.
  3. The server broadcasts the accepted ChatMessage.
  4. Each client stores the message in a reactive signal and renders it.
The default GUI is a CanvasEngine component, but presentation is replaceable without changing the server behavior.

Install

The default component also uses the semantic styles from @rpgjs/ui-css.

Configure the client

Use the explicit client entry point. This prevents server code from entering a browser bundle when standalone mode loads both runtime entry graphs.

Client options

maxMessages limits client memory only. It does not create permanent history. The server remains authoritative for maxLength; configure the same value on both sides so the built-in input rejects exactly the same message lengths.

Configure the server

Use the explicit server entry point and register it before provideServerModules():
Map chat is enabled by default. A map message is broadcast only to players in the sender’s current map. An omitted channel defaults to map; any explicitly supplied value other than map or global is rejected.

Server options and hooks

The hook order is:

Moderation example

Clients never choose the accepted author, player ID, map ID, or timestamp.

Global chat

Global chat is opt-in because the correct broadcast mechanism depends on the deployment topology. Enable the channel and provide an adapter:
The adapter is responsible for delivering the message to all intended clients, including clients hosted by another room, process, or edge location.

Client API

Replacement components and client modules can import: sendChatMessage() does not add an optimistic message. The UI changes only after the server broadcasts the accepted ChatMessage.

Message contract

Replace the CanvasEngine component

A replacement component does not receive the message history as props. Instead, it consumes the public chat signals. GUI data contains the configured position and maxLength. Create gui/custom-chat.ce:
CanvasEngine’s DOMContainer binds value={draft} in both directions. submit={submitMessage} prevents the browser’s default form navigation and passes (event, formData) to the handler. Register the replacement:
See the CanvasEngine documentation for DOMContainer, template syntax, and reactive signals.

Use a Vue component

Install and configure the RPGJS Vue overlay as described in Vue.js integration, then use a Vue component as the replacement:
The Vue component can subscribe to chatMessages.observable and chatError.observable, and submit with sendChatMessage(). Remember to unsubscribe when the component unmounts.

Themes and CSS

The default component uses semantic rpg-ui-* classes. Import the base theme:
Add the pixel theme after it:
Then apply the theme class to an ancestor, usually <body>:
You can also override individual semantic classes:

Errors and translations

The default client module provides these English translation keys:
Override them through the regular RPGJS i18n configuration. Custom components should display chatError through engine.i18n().t() instead of exposing raw translation keys.

Run the pixel chat playground

The repository includes a complete standalone and MMORPG-compatible example:
Open http://localhost:5189. The example demonstrates map broadcast, rate limiting, an afterSend automated reply, a CanvasEngine GUI, and the shared pixel theme. Private messages, voice chat, and permanent history are intentionally outside the core module.