Build for CAR-TER
CAR-TER turns an iPhone or iPad into any remote or dashboard you can describe in JSON. A layout is a JSON document — tabs, a grid, and controls — that the app renders as a swift UI. Those controls talk to your server over a persistent WebSocket mesh called MeshSocket.
Your job, as an integrator, is to write the program on the other end of that socket: the thing that feeds the displays and handles the inputs.
The mental model (five minutes)
There are three actors. See Architecture for the full picture.
- The app loads a layout and connects to a relay, joining a channel with a role.
- The relay is a small message router. It fans out broadcasts to everyone on a channel and routes point-to-point requests between members. You can run the open-source relay yourself, or use the hosted Connect+ gateway — see Connection & Pairing.
- Your server joins the same channel and does the real work: it broadcasts data the controls listen for, and receives the actions controls emit.
Two data directions, both covered in Data Flow — sync & actions:
- Server → device (
sync): a control subscribes to an event; your server broadcasts a payload; the control extracts its value via avaluePath. - Device → server (
action): a control emits an event when tapped/changed; your server handles it (and may reply).
What you'll build
A minimal integration is ~30 lines: connect, identify, and either broadcast a number on a timer or print the actions that arrive. From there you compose: telemetry dashboards, interactive controllers, chat, force-directed graphs, and dynamically-generated tabs.
- Copy-paste starting points: Recipe: Telemetry Dashboard, Recipe: Interactive Controls.
- Language guides: Building a Server in Python (uses the MeshSocket client library) or Building a Server in Any Language (Raw Protocol) (implement the frames yourself in any language).
The fastest path: Layout Link
Before writing any server code, point Layout Link at your layout:
pip install carterkit
carterkit explore # then scan the printed QR from the app
The explorer pulls the layout off your phone (or reads a local file:
carterkit explore my-layout.json) and serves a local web page with the
layout's whole wire API, typed: every trigger its controls fire, every data
feed they listen for, live inputs to push values, a running log of every frame,
and a download of a ready-to-run Python server stub for exactly that layout.
Built a layout in the on-device editor? Its top-bar laptop icon walks you
through the same three steps. Every Featured template in the app also ships
a paired *_bridge.py you can download next to the layout on this site — a
complete working system out of the box.
A complete tiny example
A layout with one gauge that listens, and one button that sends:
{
"name": "Hello CAR-TER",
"version": 1,
"connection": {
"url": "ws://192.168.1.50:8765",
"identity": { "name": "Dashboard", "channel": "demo", "role": "viewer" }
},
"tabs": [{
"title": "Main", "icon": "gauge.with.dots.needle.67percent",
"grid": { "columns": 2, "rows": 2 },
"children": [
{ "type": "gauge", "id": "cpu", "position": [0,0], "label": "CPU",
"min": 0, "max": 100,
"sync": [{ "method": "meshsocket", "type": "listen",
"event": "broadcast", "filter": { "msg_type": "metrics" },
"valuePath": "cpu" }] },
{ "type": "button", "id": "refresh", "position": [0,1], "label": "Refresh",
"action": { "method": "meshsocket", "mode": "broadcast",
"event": "broadcast_request",
"payload": { "msg_type": "command", "command": "refresh" } } }
]
}]
}
Your server, on the demo channel, broadcasts { "msg_type": "metrics", "cpu": 73 }
to move the gauge, and listens for { "msg_type": "command", "command": "refresh" }
when the button is tapped. The exact frames are spelled out in
The MeshSocket Protocol and Data Flow — sync & actions; full schema in Layout Schema.
Next: Architecture.









