Architecture
CAR-TER is a three-actor system. Understanding who owns what makes the rest of the protocol obvious.
The three actors
1. The device (CAR-TER app)
An iPhone or iPad running CAR-TER. It loads a layout (a JSON document) and renders it as a live UI. It is a thin client: it knows how to draw controls, extract values from messages, and emit actions — but it contains no business logic. Everything dynamic comes from the network.
The device joins a relay channel with a role (commonly viewer for a
dashboard, controller for a remote, or editor during live authoring).
2. The relay (MeshSocket server)
A small, generic WebSocket message router. It does not understand layouts, controls, or telemetry — it only moves frames between clients on the same channel. Two routing primitives matter:
- Broadcast — one client sends
broadcast_request; the relay re-emits it as abroadcastframe to every other member of the channel (subject to scope). This is fan-out: one server, many viewers. - Routed RPC — one client sends
route_msgtargeting another by id/name; the relay forwards it and returns the target's reply. This is point-to-point.
You have two ways to run a relay; see Connection & Pairing:
- Self-hosted — run the open-source MeshSocket relay on your LAN
(
ws://…). Zero auth, zero cost, fits hobby/home use. - Connect+ gateway — the hosted, authenticated, slot-metered service
(
wss://…) that wraps the same relay with a token gateway.
3. Your server
The program you write. It joins the same channel and supplies everything the layout needs: it broadcasts the data controls display and handles the actions controls emit. It can be a 30-line script or a full service. Language is up to you — see Building a Server in Python for the supported client library, or Building a Server in Any Language (Raw Protocol) to implement the frames directly.
How a session comes together
Nothing about the layout is known to the relay — the relay just sees frames on a
channel. The meaning lives in the conventions your layout and server agree on
(event names, msg_type discriminators, valuePaths). Those conventions are the
subject of Data Flow — sync & actions.
Channels and roles
- Channel — a namespace. Members of a channel see each other's broadcasts and
can route to each other. Use one channel per "scene" (e.g.
home,studio,rack-3). On the Connect+ gateway, channels are additionally namespaced per account, so yourhomenever collides with someone else's. - Role — a label (
viewer,controller,hub,editor,node, …) that also drives capability defaults at the relay (who may broadcast, route, or monitor the member list). You can set capabilities explicitly; see The MeshSocket Protocol.
Where layouts come from
The device can get a layout four ways — all produce the same runtime behavior:
- Bundled / on-disk JSON loaded in the app.
- The web editor (
editor/) — author visually, push to a paired device. - The MCP server (
carter-mcp) — have an LLM build and push layouts live; see Live Editing & the MCP Authoring Loop. - Hand-written JSON following the Layout Schema.
As an integrator you mostly care about the connection block of the layout and the events its controls use — the rest is presentation.
Next: The MeshSocket Protocol.