diff --git a/README.md b/README.md index 4a02fe1..f0df4a8 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,28 @@ To clear it: `localStorage.removeItem('chart-token')`. polls the latter from whatever machine you pushed from, and neither reveals anything about the market data or the configuration. +## Alerts and ntfy + +Alerts are evaluated **server-side**, once per closed 1m bar, by a single engine +living in `Runtime`. They do not depend on a browser being connected — that is the +whole point of the phone push — and opening two tabs does not double-notify. + +`NTFY_TOPIC` must be set or nothing sends; `send_ntfy` returns immediately on a blank +topic. Set it in **Coolify's environment variables** for production, not in this repo. + +**Use a different topic locally — or better, none.** Cooldown state is in memory, so +every restart starts with empty cooldowns and the first closed bar re-alerts whatever +zone price is sitting on. Locally that means every `--reload` save. Leaving +`NTFY_TOPIC` blank keeps the in-browser sound and banner while suppressing the push; +set a `-dev` topic only while testing the push path itself. + +The same applies to production, more slowly: **a deploy resets the cooldowns**, so a +zone that alerted an hour ago can alert again right after a redeploy. Persisting the +fired-zone table would fix it. + +Note that ntfy topics are public by default: anyone who knows the name can both read +your alerts and publish to it. Treat the topic name as a secret. + ## Saved trendlines Manual trendlines are written to `MANUAL_LINES_PATH` (`./data/manual_lines.json`).