Loop ergonomics

One loop, fully equipped. @loop gains sort by, offset, limit, reverse, an @empty branch, and per-row meta variables ({ $number }, { $first }, { $last }, { $count }) — all in plain Markdown, all reactive when the source or a clause argument is :state.

Sorted, numbered, with first / last markers

sort by p.age desc orders the eldest first. Each row reads its position from the loop meta vars: { $number } is the 1-based index, and :if $first / :if $last light up only on the boundary rows.

1. Cyrus — age 71

(first)

2. Dax — age 52

3. Esme — age 44

4. Ada — age 36

5. Bao — age 29

(last)

The list above is sorted oldest-first. offset is wired to a :state, so a button can slide the window without a reload:

Reactive paging with limit

limit pageSize reads a :state value, so paging is just a button that bumps the number. The runtime re-slices the same loop in place — no extra request, no reload.

Ada — age 36

Cyrus — age 71

where + @empty

where filters live as you type, and @empty renders the moment the filtered set hits zero rows — the one place a loop gets to say "nothing here":

Ada

Cyrus

Bao

Dax

Esme

reverse flips the source order

No sort key needed — reverse walks the list back to front: