Data shaping (SDA)

A focused view-shaping tool, so pages don't fill up with nested transform logic.

The problem

API responses almost never arrive in the shape a page wants. The list is nested two levels down, the field names are wrong, you need the newest five sorted by a timestamp, and half the keys should be dropped before the data reaches the template.

Two bad answers: push every adaptation into a backend endpoint (and grow a page-specific adapter for every view), or push it into the template (and grow unreadable nested loops and conditionals).

SDA is the third answer: a small declarative expression that turns one input value into exactly the shape you need.

The @shape directive

@call orders = data.orders_list({ customer: user.id })

@shape recent = orders.value with "
  [ .items
    | sort_by(-created)
    | take(5)
    | { id, total, placed: created } ]
"

@for (o of recent) {
  <li>{{= o.placed }} — {{= o.total }}</li>
}

The binding on the left is an ordinary value afterwards. The string on the right is the SDA query. It runs deterministically over the input and produces either a shaped value or one stable failure — it never partially mutates state and never reaches outside the value you gave it.

What the language does

  • Selectors instead of implicit dot traversal — .items, .user.name, .[0].
  • Optional and required extraction — distinguish "missing is fine" from "missing is an error".
  • Carrier-preserving comprehensions — map and filter over arrays and objects without losing the container type.
  • A modest predicate language for the filter step.
  • Pipe compositionselect | filter | project.
  • A small helper surface for normalisation and cleaning up keyed bags.

What it deliberately is not

SDA is a view-shaping tool, not a general query or programming language. It has no mutation, no ambient I/O, no way to call back into a page or a capability. When a transformation is genuinely business logic, it belongs in your data service, not in a shaping expression.

Server-to-client handoff

The most common use is handing a browser exactly the data it needs and nothing more:

<script id="bootstrap" type="application/json">
  {{~ sda(page.data, "{ user: .me | {name, avatar}, flags }") | json }}
</script>

Full contract: the SDA reference.