Layout & direction
How remaid arranges nodes on the canvas and how to group them into containers.
Automatic layout
You never specify x and y coordinates. remaid feeds the diagram into ELK, a layered-graph layout solver, and gets back a clean orthogonal routing. This means small edits never invalidate the layout — adding a node will not require manually nudging neighbours.
The cost is that you do not have pixel-level control. For 99% of architecture diagrams that is the right trade. If you need bespoke positioning, drop down to a vector tool.
Direction
The direction: directive controls how the layered layout flows. The four values are right (default), down, left, up.
diagram { direction: right
node a { kind: client }
node b { kind: service }
node c { kind: database }
edge x: a -> b
edge y: b -> c
}diagram { direction: down
node a { kind: client }
node b { kind: service }
node c { kind: database }
edge x: a -> b
edge y: b -> c
}Groups
Groups are visual containers. They draw a labeled rounded-rectangle around their members and are otherwise transparent — edges always connect nodes, never groups.
group <id> ["label"] [{ label: "...", parent: <other-group-id> }]A node joins a group by setting its parent property. ELK sizes each container around its children automatically.
diagram "system-param-sdk" {
direction: down
group sdk "system-param-sdk"
group infra "Consumer's Infrastructure"
node consumer { kind: client, label: "Consumer Project" }
node createFn { kind: service, label: "createParamClient()", parent: sdk }
node validator { kind: service, label: "Validator (Zod)", parent: sdk }
node repo { kind: service, label: "Repository Layer", parent: sdk }
node cacheLyr { kind: service, label: "Cache Layer", parent: sdk }
node pg { kind: database, label: "PostgreSQL", parent: infra }
node redis { kind: cache, label: "Redis", parent: infra }
edge import: consumer -> createFn { label: "import + config" }
edge wireV: createFn -> validator
edge wireR: createFn -> repo
edge wireC: createFn -> cacheLyr
edge driv: repo -> pg { label: "driver: pg" }
edge pubsub: cacheLyr -> redis { label: "cache + pub/sub" }
}Nested groups
Groups can nest by setting parent on the group itself, same syntax as on a node.
diagram {
direction: down
group cluster "Cluster"
group apis { label: "APIs", parent: cluster }
group jobs { label: "Workers", parent: cluster }
node a { kind: service, label: "users", parent: apis }
node b { kind: service, label: "orders", parent: apis }
node c { kind: service, label: "indexer", parent: jobs }
node d { kind: queue, label: "events", parent: cluster }
edge a_to_d: a -> d
edge b_to_d: b -> d
edge d_to_c: d -> c
}When to use groups
Groups make a diagram more honest when there is a real boundary in the system: a network boundary, a deployment unit, an ownership boundary, a vendor surface. Resist using them as decorative organizers — empty boxes around “backend things” add visual noise without adding meaning.