The layers
Five pieces, stacked. Each talks only to its neighbours, and you can replace any without touching the others. This page explains all five in plain language; the rest of the documentation details one layer at a time.
1 The kiosk software Unreal (or Unity, or yours). Holds the truth.
|
2 The control channel A WebSocket on port 9010. State out, commands in.
|
3 A client Anything that connects: our tablet, your tablet,
| a phone, a microcontroller, a building system.
|
4 The library (optional) Saves a web client from writing layer 3 by hand.
|
5 The app Which buttons exist, what they are called,
what each one sends.
1 · The kiosk software — the host
The thing being controlled. Today, that means Promethist Unreal — an Unreal project running the PromethistLink plugin. This plugin includes the control channel, switched on by default, requiring no additional installation on the box. See what the thing is in the Unreal guide.
Unreal is the host we ship, not the only host there can be. Everything below this layer is purposely engine-agnostic: where this documentation says "Unreal", read "whichever host this installation runs". A Unity host is being written against the same protocol, and yours can be too — Writing your own host.
The host owns every decision. It knows whether a conversation is running, whether audio is paused, how loud it is, and which language is selected. It records this as state and acts on commands. Nothing else can hold that truth, because two places holding it will eventually differ.
Building a host in another engine is supported, not a hack — Writing your own host.
2 · The control channel
A WebSocket on port 9010, path /link, carrying JSON. Two directions, two kinds of
message:
Out of the host: state. A flat list of named values — paused: true, volume: 70,
sessionActive: false. When one changes, the host sends only that change to all connected
clients. When a client first connects, it receives the whole list.
Into the host: commands. A string and usually a value — pause with true, volume with
70, restart with nothing.
There is deliberately no acknowledgement. The receipt for a command is the returned state.
Press Pause, and you know it worked when paused becomes true — for you and every other
client simultaneously.
The host also serves the tablet’s web page over HTTP on port 8080, so a tablet on the same
network needs no dedicated server.
Full detail: The wire protocol. Ports, tokens and the ini file: Quick start.
3 · A client
Anything that opens that socket. The host does not care what it is, and all connected clients have equal rights — there is no "the" tablet.
This includes screenless devices. A physical button is a client sending a command when a contact closes; a lamp is a client lighting up when a state key becomes true. See Physical buttons and other hardware.
Multiple simultaneous clients are the norm, not an edge case. Two operators, or a tablet plus
a hardware panel, stay in sync automatically by rendering the same published state. The host
caps concurrent connections (MaxClients, four by default).
4 · The library — optional
@promethist/kiosk-tablet helps build a web client, and nothing more. It provides one
package with three entry points: /protocol is types only, /core is the socket client with
no UI, and /ui offers the two web components. Take all three, one, or none — hardware
clients and host authors in other languages use none.
The library deliberately does not contain your button names, the commands they send, or the keys they read. That is layer 5, letting you use our components without inheriting our opinion about your protocol.
5 · The app — what the tablet actually is
One table in apps/tablet/src/tablet.ts defines which buttons exist, their names per
language, the commands they send, and the state keys driving them. Adding a button is an
entry there — not a library change, nor a registration with the host.
You fork this layer. Use our components and write your own table, or take the client and draw everything yourself.
See What lives where and The reference tablet.
So where do I change a thing?
| I want to change | Layer |
|---|---|
What a button is called, or what it looks like |
5 — the app (and CSS variables, layer 4) |
Which buttons exist at all |
5 — the app. Plus layer 1 if the action is new |
What a button does in Unreal |
1 — a Blueprint graph. Wiring a button |
Which languages are offered |
1 — |
Ports, tokens, whether the channel runs at all |
1 — the ini file. Quick start |
Add a whole new kind of client |
3 — write one. Nothing else changes |
Run all of this on a different engine |
Notice what is not in that table: adding a button never requires a protocol change, a library release, or teaching the host what the button means. That is the point of the split.