Freshness and offline
A widget that fetches should tell the user when its numbers are old. The SDK does the bookkeeping, so every widget looks the same.

How it works
Section titled “How it works”- Every
umbra.fetchJson/umbra.fetchTextoutcome is recorded; HTTP errors and timeouts are failures. There’s nothing to call. umbra.status.stateis:liveafter a success,stalewhen the data is older than 3× the refresh interval,offlineafter two failures in a row, or a failure when nothing has loaded since the widget started,noneuntil the first fetch finishes.
<html data-stale>is set while the state isstaleoroffline. Dim your numbers with CSS (keep it toopacity):
html[data-stale] .price { opacity: 0.55; }The status dot
Section titled “The status dot”<umbra-status></umbra-status> is an optional element, styled by umbra.css with tokens: a small dot (--up live, --text-3 stale, a ring when offline). Hovering it shows “Updated 3 min ago”; offline keeps “Offline · last data 10:42” visible. Put it in a footer, and use placement="below-end" in a top-right header so the hover text opens downwards. It’s hidden while the state is none.
Overriding the bookkeeping
Section titled “Overriding the bookkeeping”umbra.status.failed(err)for a response you can’t use (a fetch’s own Error is only counted once).umbra.status.ok(new Date(savedAt))to show data restored fromumbra.storeas “last data” at startup.umbra.status.onChange(fn)callsfn(state)when the state changes.
Testing the offline state
Section titled “Testing the offline state”Start Umbra from a shell with UMBRA_SIMULATE_OFFLINE=1; every host fetch then fails:
$env:UMBRA_SIMULATE_OFFLINE = 1dotnet run --project src/Umbra # or start the installed Umbra.exe from this shell