Edit: Just had a bit of time off and could restructure this post a bit.
Hello @ykremer , welcome to the forum,
What you are experiencing has been commented on before:
In your particular case, it is not zero, it is none.
Knowing that, there are a few solutions available for you, including but not limited to:
Using Hydra Package
With Typst Headings
Hydra is designed specifically for that purpose. You can use any heading level you want and it is highly configurable.
This is a working example showing the last defined exercise (here we are using level 1 headings) in the header:
#import "@preview/hydra:0.6.2": hydra
#set page(
header: context {
hydra(use-last: true, skip-starting: false)
line(length: 100%)
},
)
= Exercise 1
= Exercise 2
= Exercise 3
With Custom Element
If you don’t want to use the heading elements, you can define some custom ones for your needs. The key is to define a way for Hydra to display the custom element.
hydra is built with custom elements in mind. Some documents may use other elements for chapters or section-like content. hydra allows defining its own selectors for tight control over how elements are queried.
See Hydra’s documentation for more information.
#import "@preview/hydra:0.6.2": hydra
#let exercise(body, label: none) = {
show figure: set align(left)
set figure(numbering: "1")
[#figure(kind: "exercise", supplement: [Exercise], caption: body, none)
#label]
}
#set page(
paper: "a5",
header: context {
hydra(
figure.where(kind: "exercise"),
display: (.., it) => it.caption,
use-last: true,
skip-starting: false,
)
line(length: 100%)
},
)
#for n in range(1, 4) {
exercise([#lorem(1)], label: <n>)
}
Without any Packages
Another Solution using Query
This is adapted from How do I count elements on a page so the result isn't always zero in the header? - #7 by janekfleper and uses query instead of state. No packages are needed.
#let exercise(body, label: none) = {
show figure: set align(left)
set figure(numbering: "1")
[#figure(kind: "exercise", supplement: [Exercise], caption: body, none)
#label]
}
// Find the last exercise on the current page
#let last-exercise() = {
let ex = query(figure.where(kind: "exercise"))
if ex.len() > 0 {
ex.filter(it => it.location().page() == here().page()).last().caption
}
}
#set page(
header: context {
last-exercise()
line(length: 100%)
},
)
#for n in range(1, 4) {
exercise([#lorem(1)], label: <n>)
}


