Skip to main content

Packets (dynamic objects)

Where nodes are static, packets (packets) are the dynamic objects: the payloads that move from one node to another. You declare them once in the packets root array, then you animate them by their id with the move action.

A single packet can be moved multiple times in the timeline (forward, then back, then transferred...): it is the exact same visual entity traveling.

Loading…

kind — the packet nature

The kind determines the appearance and available content fields:

kindRepresentsContent field
http_packetAn HTTP request/responsepacket_content
sql_requestA SQL queryrequest_content
sql_responseA SQL resultresponse_content
simple_nodeA traveling text boxbody / language
complex_nodeA traveling header + bodyheader / body / language
subiconA traveling tech badgeicon

http_packetpacket_content

An envelope with a header (header, e.g., the request line) and an optional body (body). The body accepts text (with optional syntax highlighting) or an image.

{
id: 'req',
kind: 'http_packet',
packet_content: {
header: 'GET /users',
body: { type: 'text', value: 'Accept: application/json' },
},
}

For a response, we reuse the same shape with a highlighted body:

{
id: 'res',
kind: 'http_packet',
packet_content: {
header: '200 OK',
body: { type: 'text', value: '[{ "id": 1 }]', language: 'json' },
},
}

sql_requestrequest_content

The simplest: a string representing the query. It is displayed inside the packet as it moves to the database.

{
id: 'sql',
kind: 'sql_request',
request_content: 'SELECT id, name FROM users',
}

sql_responseresponse_content

The result returned by the database. It specifies the number of rows (rows), an optional header (header), and a body (body) which can be text or a table:

{
id: 'rows',
kind: 'sql_response',
response_content: {
header: '2 rows',
body: {
type: 'table',
columns: ['id', 'name'],
rows_data: [
[1, 'Alice'],
[2, 'Bob'],
],
},
},
}
rows vs body

rows is a simple counter displayed in the header; body carries the actual rendered content (text or table). A sql_response without a body only displays its header.

simple_node / complex_node — a node that travels

The text panel node types double as packet kinds: declare a packet with kind: 'simple_node' or kind: 'complex_node' and it carries the same content fields as the nodebody, plus header for complex_node, optionally syntax-highlighted via language. No nested *_content object: it is the node, but it moves.

{
id: 'msg',
kind: 'simple_node',
body: 'enqueue(job)',
language: 'js',
}

complex_node adds the header line, just like the static node — handy when you already use that node type in the scene and want the matching payload to fly:

{
id: 'login',
kind: 'complex_node',
header: 'POST /login',
body: '{ "user": "alice" }',
language: 'json',
}
complex_node vs http_packet

Both render a header above a body. Reach for complex_node when you want the packet to look exactly like a complex_node node already on stage (same box, same body/header/language API); keep http_packet for its dedicated packet_content shape (typed body, image bodies).

subicon — a tech badge that travels

The node subicon — the small corner badge naming a technology — doubles as a packet kind: declare a packet with kind: 'subicon' and an icon, and the badge travels on its own. icon takes the same values as the node's: a known technology (react, postgres…), a registered icon, or short free text (v2, API).

{
id: 'lib',
kind: 'subicon',
icon: 'react',
}

It is resolved by the same getSubIcon as the node badge — any name your nodes already use works here too — and the moving wrapper renders as a round badge.

Setting a packet in motion

Declaring a packet does not display it: it only appears during a move.

timeline: [
{ type: 'move', object: 'req', from: 'browser', to: 'api' },
{ type: 'move', object: 'sql', from: 'api', to: 'db' },
],

See Action types → move for durations, the bidirectional lane offset and persistence.