Blocks

Reshape

The reshape step: every list manipulation in one tile — filter, sort, remove duplicates, limit, split out, aggregate — no code.

Every list manipulation in one step. Point it at a list, pick a task:

task what it does
filter keep the items matching a condition
sort order by a per-item key
remove duplicates drop repeats by a compare key (first one wins)
limit keep the first or last N
split out lift a nested array up to the top-level items list
aggregate collapse a list into one value

Config

The reshape step in the Inspector The task picker decides which fields show; every task starts from the same List expression.

  • List — an expression picking the list off the upstream output: payload["items"]. Bracket access, same dialect as loop's over.
  • Per-task fields — filter's Keep when, sort's Sort by + order, remove-duplicates' compare key, limit's max + first/last, aggregate's mode.

Per-item expressions see three bindings: item (the element), index (0-based), and payload (the whole upstream output) — so item["score"] > payload["threshold"] works.

Output

filter / sort / remove duplicates / limit / split out share one envelope:

{ "items": [ ], "count": 12 }

(filter adds "dropped".) Feed payload.items straight into a loop or the next reshape. Aggregate emits per its mode: all_items nests the whole list under one key; fields collects named fields across items into parallel lists ({"emails": […], "count": 3}).

Patterns

  • Top 5 digest — filter (item["score"] > 50) → sort desc → limit 5 → summarize.
  • Dedupe then act — remove duplicates by item["email"] → loop → send.
  • Chain them — each reshape outputs items, so the next one's List is just payload["items"].

Gotchas

  • Filter is per-item. For a yes/no gate on the whole payload, use if instead.
  • Sort compares numbers, strings, and ISO-8601 dates sensibly — but only if the key returns the same type for every item.
  • Something these six can't express → run code.