- pnpm 10 workspace + TypeScript strict + ESLint flat + Prettier - CLAUDE.md as canonical brief - docs/tasks/ — 22 task briefs broken out by phase for sub-sessions - docs/decisions/ — ADR scaffold Implements task 01 (repo-init).
29 lines
984 B
Markdown
29 lines
984 B
Markdown
# 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.
|