editordocs · v0.1.0
reference

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
}
diagramDiagram with 3 nodes and 2 edges.abc
direction: right (default).
diagram { direction: down
  node a { kind: client }
  node b { kind: service }
  node c { kind: database }
  edge x: a -> b
  edge y: b -> c
}
diagramDiagram with 3 nodes and 2 edges.abc
Same diagram with direction: down.

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" }
}
system-param-sdkDiagram with 7 nodes and 6 edges.SYSTEM-PARAM-SDKCONSUMER'S INFRASTRUCTUREimport + configdriver: pgcache + pub/subConsumer ProjectcreateParamClient()Validator (Zod)Repository LayerCache LayerPostgreSQLRedis
A real-world example: an SDK in one container, the consumer's infrastructure in another.

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
}
diagramDiagram with 4 nodes and 3 edges.CLUSTERAPISWORKERSusersordersindexerevents
Two sub-groups (APIs, Workers) inside a parent Cluster group.

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.