I would have a look at how hydra – Typst Universe is dealing with this (with anchors I believe). It may even be working out of the box for this purpose.
Edit: This is a start, adapted from How do I count elements on a page so the result isn't always zero in the header? - #7 by janekfleper
#let exercise(body, label: none) = [
#show figure: set align(left)
#set figure(numbering: "1.")
#show figure.caption: it => context {
strong(it.counter.display()) + [ ]
it.supplement + [: ]
linebreak()
it.body
}
#figure(kind: "exercise", supplement: "Ex", [], caption: body)
#label
]
#let disp-exercises() = {
let ex = query(figure.where(kind: "exercise"))
ex.filter(it => it.location().page() == here().page()).first()
}
#set page(
header: context disp-exercises(),
footer: context disp-exercises(),
)
#exercise(lorem(2))
#exercise(lorem(2))
#exercise(lorem(2))
#exercise(lorem(2))
#pagebreak()
#exercise(lorem(2))
#exercise(lorem(2))
#exercise(lorem(2))