# 42 — Notification bus + ntfy adapter ## Goal Single `notify()` entrypoint that fans out to web push, in-app inbox, and (optionally) ntfy. ## Depends on - 40 ## Scope - `_core/notify.ts` — `notify(userId, { title, body, url, channels? })`. - Channels: `push`, `inapp`, `ntfy`. Default: `['push', 'inapp']`. - In-app inbox: `notifications` table (`id`, `user_id`, `title`, `body`, `url`, `read_at`, `created_at`); bell icon in header with unread count and dropdown. - ntfy adapter: if `NTFY_URL` and `NTFY_TOPIC` env are set, also POSTs there. Off by default; Matt opts in. - Per-user toggles in `/settings` for each channel. ## Out of scope - Email notifications. - Per-event-type routing rules (Matt can add later as a module). ## Acceptance criteria - [ ] `notify()` with default channels delivers push + in-app and ignores ntfy. - [ ] Setting `NTFY_URL`+`NTFY_TOPIC` and toggling on in settings adds ntfy delivery. - [ ] Unread count is accurate and clears on read.