notifkit 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +130 -122
- package/dist/index.d.mts +196 -132
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/{main-DtHWhueo.mjs → main-40zwq6b0.mjs} +28 -3
- package/dist/{main-DtHWhueo.mjs.map → main-40zwq6b0.mjs.map} +1 -1
- package/dist/{main-DyfbnJc3.mjs → main-BFre2-HQ.mjs} +2 -2
- package/dist/{main-DyfbnJc3.mjs.map → main-BFre2-HQ.mjs.map} +1 -1
- package/dist/{main-CAH0_Q6d.mjs → main-BNJtzY61.mjs} +3 -3
- package/dist/main-BNJtzY61.mjs.map +1 -0
- package/dist/{main-B561M1d3.mjs → main-BOPMYqsW.mjs} +2 -2
- package/dist/{main-B561M1d3.mjs.map → main-BOPMYqsW.mjs.map} +1 -1
- package/dist/{main-CCfc45ev.mjs → main-CiigNpsP.mjs} +7 -4
- package/dist/main-CiigNpsP.mjs.map +1 -0
- package/dist/{main-Ce9dcrsg.mjs → main-DeNFQ-UL.mjs} +6 -3
- package/dist/{main-Ce9dcrsg.mjs.map → main-DeNFQ-UL.mjs.map} +1 -1
- package/dist/{main-B-jwm8ED.mjs → main-DmCPcxOc.mjs} +2 -2
- package/dist/{main-B-jwm8ED.mjs.map → main-DmCPcxOc.mjs.map} +1 -1
- package/dist/{main-C45e7grq.mjs → main-DvgJSm11.mjs} +2 -2
- package/dist/{main-C45e7grq.mjs.map → main-DvgJSm11.mjs.map} +1 -1
- package/dist/{src-C-PfEDMY.mjs → src-vG79L-8m.mjs} +57 -26
- package/dist/src-vG79L-8m.mjs.map +1 -0
- package/drizzle/0002_wide_colleen_wing.sql +2 -0
- package/drizzle/0003_skinny_daimon_hellstrom.sql +1 -0
- package/drizzle/0004_pretty_bruce_banner.sql +1 -0
- package/drizzle/meta/0002_snapshot.json +1460 -0
- package/drizzle/meta/0003_snapshot.json +1460 -0
- package/drizzle/meta/0004_snapshot.json +1470 -0
- package/drizzle/meta/_journal.json +21 -0
- package/package.json +3 -2
- package/src/client.ts +412 -0
- package/src/config/index.ts +107 -0
- package/src/contracts/common.ts +28 -0
- package/src/contracts/envelope.ts +31 -0
- package/src/contracts/events/notification-ai-pending.ts +18 -0
- package/src/contracts/events/notification-canceled.ts +7 -0
- package/src/contracts/events/notification-created.ts +14 -0
- package/src/contracts/events/notification-delivered.ts +17 -0
- package/src/contracts/events/notification-dispatched.ts +45 -0
- package/src/contracts/events/notification-enriched.ts +46 -0
- package/src/contracts/events/notification-failed.ts +19 -0
- package/src/contracts/events/notification-requested.ts +36 -0
- package/src/contracts/events/notification-scheduled.ts +9 -0
- package/src/contracts/events/notification-skipped.ts +9 -0
- package/src/contracts/helpers.ts +21 -0
- package/src/contracts/index.ts +46 -0
- package/src/contracts/metadata.ts +10 -0
- package/src/contracts/registry.ts +88 -0
- package/src/contracts/sdk.ts +242 -0
- package/src/contracts/streams.ts +62 -0
- package/src/db/index.ts +69 -0
- package/src/db/schema.ts +412 -0
- package/src/idempotency/index.ts +50 -0
- package/src/index.ts +19 -0
- package/src/logger/index.ts +60 -0
- package/src/metrics/index.ts +53 -0
- package/src/queue/index.ts +501 -0
- package/src/rate-limiter/index.ts +210 -0
- package/src/redis/index.ts +89 -0
- package/src/repositories/index.ts +1246 -0
- package/src/server.ts +277 -0
- package/src/services/ai/main.ts +404 -0
- package/src/services/api/handlers.ts +1734 -0
- package/src/services/api/http.ts +64 -0
- package/src/services/api/main.ts +693 -0
- package/src/services/api/router.ts +82 -0
- package/src/services/delivery/main.ts +842 -0
- package/src/services/delivery/throttle.ts +71 -0
- package/src/services/engine/main.ts +827 -0
- package/src/services/enricher/main.ts +594 -0
- package/src/services/events/main.ts +365 -0
- package/src/services/scheduler/main.ts +319 -0
- package/src/services/workflow/main.ts +627 -0
- package/src/shared/batch-processor.ts +67 -0
- package/src/shared/cache.ts +47 -0
- package/src/shared/circuit-breaker.ts +74 -0
- package/src/shared/dataloader.ts +41 -0
- package/src/shared/events.ts +3 -0
- package/src/shared/index.ts +39 -0
- package/src/shared/semaphore.ts +33 -0
- package/src/shared/utils.ts +64 -0
- package/src/templates/cache.ts +32 -0
- package/src/templates/index.ts +69 -0
- package/src/templates/render.ts +128 -0
- package/src/transport/index.ts +96 -0
- package/src/unsubscribe/index.ts +127 -0
- package/src/workers/health.ts +31 -0
- package/src/workers/index.ts +266 -0
- package/src/workflows/index.ts +2 -0
- package/src/workflows/registry.ts +21 -0
- package/src/workflows/sdk.ts +106 -0
- package/dist/main-CAH0_Q6d.mjs.map +0 -1
- package/dist/main-CCfc45ev.mjs.map +0 -1
- package/dist/src-C-PfEDMY.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
Self-hosted notification infrastructure for product notifications. One API call handles email, SMS, push, and webhooks — with preferences, quiet hours, retries, fallback, scheduling, workflows, and delivery logs built in.
|
|
8
8
|
|
|
9
|
-
[](https://www.npmjs.com/package/notifkit) [](https://www.npmjs.com/package/notifkit) [](https://www.npmjs.com/package/notifkit) [](https://www.npmjs.com/package/notifkit) [](https://github.com/devkitshq/notifkit/actions/workflows/ci.yml) [](https://www.typescriptlang.org/) [](https://nodejs.org) [](./LICENSE)
|
|
10
10
|
|
|
11
11
|
[Documentation](https://notifkit.dev/docs/) · [Quickstart](https://notifkit.dev/docs/quickstart.html) · [Examples](https://notifkit.dev/docs/examples.html) · [notifkit.dev](https://notifkit.dev)
|
|
12
12
|
|
|
@@ -53,50 +53,40 @@ await notifkit.notify({
|
|
|
53
53
|
|
|
54
54
|
notifkit is both an **orchestration engine** and a **typed SDK**.
|
|
55
55
|
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
│ └─────────────┘ │
|
|
91
|
-
└──────────────────────────────────┬───────────────────────┘
|
|
92
|
-
│ Dispatch
|
|
93
|
-
▼
|
|
94
|
-
┌──────────────────────────────────────────────────────────┐
|
|
95
|
-
│ Provider Transports │
|
|
96
|
-
│ │
|
|
97
|
-
│ Email: Resend, SES, Postmark Push: Firebase (FCM) │
|
|
98
|
-
│ SMS: Twilio, MessageBird Webhooks: Custom HTTP │
|
|
99
|
-
└──────────────────────────────────────────────────────────┘
|
|
56
|
+
```mermaid
|
|
57
|
+
flowchart TD
|
|
58
|
+
App["Your Application / AI Agent<br/>Typed SDK · REST API · MCP Server"]
|
|
59
|
+
|
|
60
|
+
App -->|"HTTP POST /v1/notify"| API
|
|
61
|
+
|
|
62
|
+
API["Notifkit API Server<br/>Schema Validation · Auth · Multi-Tenancy<br/>Idempotency Gate · Priority Queue Ingestion"]
|
|
63
|
+
|
|
64
|
+
API --> PG
|
|
65
|
+
API --> REDIS
|
|
66
|
+
|
|
67
|
+
PG[("PostgreSQL — Storage<br/>Users · Preferences<br/>Templates · Workflows<br/>Delivery Logs · DLQ")]
|
|
68
|
+
REDIS[("Redis — Streams / ZSET<br/>Priority Queues<br/>Scheduled Sends<br/>Sliding Rate Limits")]
|
|
69
|
+
|
|
70
|
+
subgraph WORKERS["Background Workers Pipeline"]
|
|
71
|
+
direction LR
|
|
72
|
+
ENRICH["Enricher<br/>(Resolve)"] --> ENGINE["Engine<br/>(Quiet Hours)"] --> DELIVER["Delivery<br/>(Rate Limits / CB)"]
|
|
73
|
+
ENGINE --> SCHED["Scheduler<br/>(sendAt / QH)"]
|
|
74
|
+
SCHED --> DELIVER
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
REDIS -->|"consume"| ENRICH
|
|
78
|
+
ENRICH -.->|"read / write state"| PG
|
|
79
|
+
DELIVER -.->|"delivery logs"| PG
|
|
80
|
+
DELIVER -->|"Dispatch"| PROVIDERS
|
|
81
|
+
|
|
82
|
+
PROVIDERS["Provider Transports<br/>Email: Resend, SES, Postmark · Push: Firebase (FCM)<br/>SMS: Twilio, MessageBird · Webhooks: Custom HTTP"]
|
|
83
|
+
|
|
84
|
+
classDef entry stroke:#6366f1,stroke-width:2px
|
|
85
|
+
classDef store stroke:#0ea5e9,stroke-width:2px
|
|
86
|
+
classDef work stroke:#22c55e,stroke-width:2px
|
|
87
|
+
class App,API,PROVIDERS entry
|
|
88
|
+
class PG,REDIS store
|
|
89
|
+
class ENRICH,ENGINE,DELIVER,SCHED work
|
|
100
90
|
```
|
|
101
91
|
|
|
102
92
|
- **`NotifkitServer`**: Runs the HTTP REST API router (`/v1/notify`, `/health`, `/metrics`) and the background worker pipelines (enricher, decision engine, scheduler, delivery).
|
|
@@ -109,67 +99,61 @@ notifkit is both an **orchestration engine** and a **typed SDK**.
|
|
|
109
99
|
|
|
110
100
|
---
|
|
111
101
|
|
|
112
|
-
##
|
|
102
|
+
## Agent-operable
|
|
113
103
|
|
|
114
|
-
|
|
115
|
-
>
|
|
116
|
-
> It is the infrastructure we built because we needed it ourselves — rather than spending months reinventing distributed notification plumbing or paying SaaS tolls per alert.
|
|
104
|
+
https://github.com/user-attachments/assets/4dff98bb-37d3-44b4-bf46-9607c1cd89b5
|
|
117
105
|
|
|
118
|
-
|
|
106
|
+
[▶️ Watch the AI demo](assets/ai_demo.mp4) - this is link to raw video file
|
|
119
107
|
|
|
120
|
-
|
|
108
|
+
**notifkit isn't just an API your application can call — your AI agent can operate it directly.**
|
|
121
109
|
|
|
122
|
-
|
|
110
|
+
Connect the notifkit MCP server ([`@notifkit/mcp`](./packages/mcp)) to Claude Code, Cursor, Claude Desktop, Gemini, or any MCP-compatible agent:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npx -y @notifkit/mcp
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Ask your agent
|
|
123
117
|
|
|
124
118
|
```text
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
│ Connection Loss│ ──( Disconnect )──► │ Auto-Reconnect / Retry │ ──► In-Flight State Intact
|
|
130
|
-
└────────────────┘ └────────────────────────┘
|
|
131
|
-
┌────────────────┐ High Load ┌────────────────────────┐
|
|
132
|
-
│ 10k+ Messages │ ──( Burst )───────► │ Concurrency & Limits │ ──► Flat Memory, No Leaks
|
|
133
|
-
└────────────────┘ └────────────────────────┘
|
|
119
|
+
You: Why didn't usr_9182 receive their password reset?
|
|
120
|
+
|
|
121
|
+
Agent: The notification was suppressed because usr_9182's email
|
|
122
|
+
address has a hard-bounce suppression from yesterday.
|
|
134
123
|
```
|
|
135
124
|
|
|
136
|
-
|
|
137
|
-
- **Infrastructure Recovery Testing (`tests/chaos/recovery.test.ts`)**: PostgreSQL and Redis connections are forcefully severed and restored under live traffic. Verifies automatic client reconnection, worker backpressure, and durable state resumption.
|
|
138
|
-
- **High-Throughput Load Testing (`tests/chaos/load.test.ts`)**: Stressed with bursts of **10,000+ notifications** across parallel worker pools, verifying queue drain velocity, sliding-window rate limiters, and flat memory profiles without leaks.
|
|
139
|
-
- **Race Conditions & Concurrency (`tests/race-conditions.test.ts`, `tests/idempotency.test.ts`)**: Hardened against concurrent duplicate dispatches, overlapping quiet-hour boundary evaluations, atomic user updates, and 24-hour idempotency key deduplication.
|
|
140
|
-
- **100% Real Ephemeral Containers**: Unit, integration, and chaos test suites execute against real PostgreSQL and Redis containers via [Testcontainers](https://testcontainers.com), eliminating mocks for core storage and streaming primitives.
|
|
125
|
+
Your application and your AI agents use the **same notification infrastructure**:
|
|
141
126
|
|
|
142
|
-
|
|
127
|
+
- **Send & dispatch** — Send one-off notifications or campaigns to users, lists, and segments (`send_notification`, `send_campaign`)
|
|
128
|
+
- **Investigate & triage** — Diagnose delivery issues by inspecting message histories, provider responses, and quiet hours (`get_delivery_logs`, `get_notification`)
|
|
129
|
+
- **Schedule & cancel** — Schedule future sends and cancel pending notifications (`list_scheduled`, `cancel_notification`)
|
|
130
|
+
- **Campaign analytics** — Check delivery, open, click, bounce, and complaint metrics (`list_campaigns`, `get_campaign_stats`)
|
|
131
|
+
- **Template management** — List, preview, and update templates with sample data (`list_templates`, `preview_template`, `upsert_template`)
|
|
132
|
+
- **Users & preferences** — Look up users, contacts, preferences, and segment membership (`list_users`, `get_user_preferences`, `update_user_preferences`)
|
|
133
|
+
- **Workflow operations** — Trigger workflows and inspect workflow runs (`create_workflow`, `trigger_workflow`, `get_workflow_run`)
|
|
134
|
+
- **Suppressions & health** — Manage bounce suppressions, check system queues, and replay dead-letter messages (`list_suppressions`, `get_dead_letters`, `replay_dead_letter`)
|
|
143
135
|
|
|
144
|
-
|
|
136
|
+
### From “write a script” to “just ask”
|
|
145
137
|
|
|
146
|
-
|
|
|
147
|
-
|
|
|
148
|
-
|
|
|
149
|
-
| **“Is this a bad time to send?”** | Timezone-aware quiet hours that defer non-urgent sends |
|
|
150
|
-
| **“What if push fails?”** | Automatic ordered multi-channel fallback (`push` → `email` → `sms`) |
|
|
151
|
-
| **“What if my worker crashes?”** | Redis Streams consumer groups, retries, and durable idempotency |
|
|
152
|
-
| **“What if an event fires twice?”** | 24-hour deduplication via idempotency keys |
|
|
153
|
-
| **“Can I send this later?”** | Priority scheduling with `sendAt` and cancellation before dispatch |
|
|
154
|
-
| **“Can I send this 3 days after signup?”** | Stateful multi-step workflows with `wait` and `waitForEvent` |
|
|
155
|
-
| **“How do I know what happened?”** | Queryable delivery logs, Prometheus metrics, and campaign reporting |
|
|
156
|
-
| **“What happens when a provider goes down?”** | Circuit breakers, exponential backoff, and DLQ replay |
|
|
157
|
-
| **“What about bounces and spam complaints?”** | RFC 8058 one-click unsubscribe and automatic hard-bounce suppression |
|
|
158
|
-
| **“What if I don't want another SaaS holding my data?”** | 100% self-hosted on your PostgreSQL and Redis |
|
|
138
|
+
| Without an agent | With NotifKit MCP |
|
|
139
|
+
| :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
140
|
+
| Jump into the DB to find contact info → open Twilio/Resend or write a throwaway script → format the payload → check their timezone manually → fire it off → hope it delivered | **You:** _“Send an urgent update to alex@acme.com that his package was lost in transit and support is rushing a replacement — text him if push doesn't deliver.”_<br><br>**Agent:** Looks up `alex@acme.com` → renders template → dispatches push with SMS fallback → bypasses quiet hours for urgent delivery → tracks delivery status → confirms it hit his phone |
|
|
159
141
|
|
|
160
|
-
|
|
142
|
+
[Set up MCP](https://notifkit.dev/docs/mcp.html) · [MCP documentation](https://notifkit.dev/docs/mcp.html)
|
|
161
143
|
|
|
162
144
|
---
|
|
163
145
|
|
|
164
|
-
##
|
|
146
|
+
## AI-assisted migration
|
|
165
147
|
|
|
166
|
-
|
|
148
|
+
Already have notification code scattered across your application?
|
|
167
149
|
|
|
168
|
-
|
|
150
|
+
Point your coding agent at:
|
|
169
151
|
|
|
170
|
-
|
|
152
|
+
```text
|
|
153
|
+
https://notifkit.dev/llms-full.txt
|
|
154
|
+
```
|
|
171
155
|
|
|
172
|
-
|
|
156
|
+
It can understand notifkit's API and help identify ad-hoc notification code in your repository and refactor it into durable notifkit calls.
|
|
173
157
|
|
|
174
158
|
---
|
|
175
159
|
|
|
@@ -241,57 +225,69 @@ curl -X POST http://localhost:3000/v1/notify \
|
|
|
241
225
|
|
|
242
226
|
---
|
|
243
227
|
|
|
244
|
-
##
|
|
245
|
-
|
|
246
|
-
**notifkit isn't just an API your application can call — your AI agent can operate it directly.**
|
|
228
|
+
## Battle-tested for production
|
|
247
229
|
|
|
248
|
-
|
|
230
|
+
> **Battle-tested in production:** notifkit powers production notification pipelines handling **thousands of emails, push notifications, and OTPs every day.**
|
|
231
|
+
>
|
|
232
|
+
> It is the infrastructure we built because we needed it ourselves — rather than spending months reinventing distributed notification plumbing or paying SaaS tolls per alert.
|
|
249
233
|
|
|
250
|
-
|
|
251
|
-
npx -y @notifkit/mcp
|
|
252
|
-
```
|
|
234
|
+
**Your servers. Your providers. Your data. Zero notification SaaS markups.**
|
|
253
235
|
|
|
254
|
-
###
|
|
236
|
+
### Reliability & Chaos Engineering
|
|
255
237
|
|
|
256
|
-
|
|
257
|
-
You: Why didn't usr_9182 receive their password reset?
|
|
238
|
+
Because notification delivery is mission-critical, every pipeline component is tested against extreme failure conditions:
|
|
258
239
|
|
|
259
|
-
|
|
260
|
-
|
|
240
|
+
```mermaid
|
|
241
|
+
flowchart LR
|
|
242
|
+
S1["Redis Streams"] -->|"Kill Worker (SIGKILL)"| M1["Auto-Claim and Replay"] --> O1["Zero Lost Messages"]
|
|
243
|
+
S2["Connection Loss"] -->|"Drop DB / Redis"| M2["Auto-Reconnect / Retry"] --> O2["In-Flight State Intact"]
|
|
244
|
+
S3["10k+ Messages"] -->|"Burst"| M3["Concurrency and Limits"] --> O3["Flat Memory, No Leaks"]
|
|
245
|
+
|
|
246
|
+
classDef fault stroke:#ef4444,stroke-width:2px
|
|
247
|
+
classDef guard stroke:#6366f1,stroke-width:2px
|
|
248
|
+
classDef result stroke:#22c55e,stroke-width:2px
|
|
249
|
+
class S1,S2,S3 fault
|
|
250
|
+
class M1,M2,M3 guard
|
|
251
|
+
class O1,O2,O3 result
|
|
261
252
|
```
|
|
262
253
|
|
|
263
|
-
|
|
254
|
+
- **Chaos Monkey Testing (`tests/chaos/crash.test.ts`)**: Background worker processes are randomly terminated with `SIGKILL` during active, high-throughput message streaming. Consumer group Pending Entries List (PEL) re-claims guarantee **zero lost messages** and seamless failover.
|
|
255
|
+
- **Infrastructure Recovery Testing (`tests/chaos/recovery.test.ts`)**: PostgreSQL and Redis connections are forcefully severed and restored under live traffic. Verifies automatic client reconnection, worker backpressure, and durable state resumption.
|
|
256
|
+
- **High-Throughput Load Testing (`tests/chaos/load.test.ts`)**: Stressed with bursts of **10,000+ notifications** across parallel worker pools, verifying queue drain velocity, sliding-window rate limiters, and flat memory profiles without leaks.
|
|
257
|
+
- **Race Conditions & Concurrency (`tests/race-conditions.test.ts`, `tests/idempotency.test.ts`)**: Hardened against concurrent duplicate dispatches, overlapping quiet-hour boundary evaluations, atomic user updates, and 24-hour idempotency key deduplication.
|
|
258
|
+
- **100% Real Ephemeral Containers**: Unit, integration, and chaos test suites execute against real PostgreSQL and Redis containers via [Testcontainers](https://testcontainers.com), eliminating mocks for core storage and streaming primitives.
|
|
264
259
|
|
|
265
|
-
|
|
266
|
-
- **Investigate & triage** — Diagnose delivery issues by inspecting message histories, provider responses, and quiet hours (`get_delivery_logs`, `get_notification`)
|
|
267
|
-
- **Schedule & cancel** — Schedule future sends and cancel pending notifications (`list_scheduled`, `cancel_notification`)
|
|
268
|
-
- **Campaign analytics** — Check delivery, open, click, bounce, and complaint metrics (`list_campaigns`, `get_campaign_stats`)
|
|
269
|
-
- **Template management** — List, preview, and update templates with sample data (`list_templates`, `preview_template`, `upsert_template`)
|
|
270
|
-
- **Users & preferences** — Look up users, contacts, preferences, and segment membership (`list_users`, `get_user_preferences`, `update_user_preferences`)
|
|
271
|
-
- **Workflow operations** — Trigger workflows and inspect workflow runs (`create_workflow`, `trigger_workflow`, `get_workflow_run`)
|
|
272
|
-
- **Suppressions & health** — Manage bounce suppressions, check system queues, and replay dead-letter messages (`list_suppressions`, `get_dead_letters`, `replay_dead_letter`)
|
|
260
|
+
---
|
|
273
261
|
|
|
274
|
-
|
|
262
|
+
## What you get
|
|
275
263
|
|
|
276
|
-
|
|
|
277
|
-
|
|
|
278
|
-
|
|
|
264
|
+
| The problem you don't want to build | How notifkit solves it |
|
|
265
|
+
| :------------------------------------------------------- | :------------------------------------------------------------------- |
|
|
266
|
+
| **“Should this user receive it?”** | User preferences, topic opt-outs, and consent gates |
|
|
267
|
+
| **“Is this a bad time to send?”** | Timezone-aware quiet hours that defer non-urgent sends |
|
|
268
|
+
| **“What if push fails?”** | Automatic ordered multi-channel fallback (`push` → `email` → `sms`) |
|
|
269
|
+
| **“What if my worker crashes?”** | Redis Streams consumer groups, retries, and durable idempotency |
|
|
270
|
+
| **“What if an event fires twice?”** | 24-hour deduplication via idempotency keys |
|
|
271
|
+
| **“Can I send this later?”** | Priority scheduling with `sendAt` and cancellation before dispatch |
|
|
272
|
+
| **“Can I send this 3 days after signup?”** | Stateful multi-step workflows with `wait` and `waitForEvent` |
|
|
273
|
+
| **“How do I know what happened?”** | Queryable delivery logs, Prometheus metrics, and campaign reporting |
|
|
274
|
+
| **“What happens when a provider goes down?”** | Circuit breakers, exponential backoff, and DLQ replay |
|
|
275
|
+
| **“What about bounces and spam complaints?”** | RFC 8058 one-click unsubscribe and automatic hard-bounce suppression |
|
|
276
|
+
| **“What if I don't want another SaaS holding my data?”** | 100% self-hosted on your PostgreSQL and Redis |
|
|
279
277
|
|
|
280
|
-
|
|
278
|
+
> **The idea is simple:** You decide what to say. **notifkit handles getting it there reliably.**
|
|
281
279
|
|
|
282
280
|
---
|
|
283
281
|
|
|
284
|
-
##
|
|
282
|
+
## What notifkit is — and what it isn't
|
|
285
283
|
|
|
286
|
-
|
|
284
|
+
**What it is:** the durable notification infrastructure layer running directly inside your own stack.
|
|
287
285
|
|
|
288
|
-
|
|
286
|
+
**What it isn't:** a marketing automation suite.
|
|
289
287
|
|
|
290
|
-
|
|
291
|
-
https://notifkit.dev/llms-full.txt
|
|
292
|
-
```
|
|
288
|
+
notifkit is not Customer.io, OneSignal, or SendGrid. You bring your own provider accounts — your keys, your billing, your deliverability.
|
|
293
289
|
|
|
294
|
-
|
|
290
|
+
First-party providers ship for Resend and Firebase Cloud Messaging. Anything else is a simple `Transport` class with a `send()` method.
|
|
295
291
|
|
|
296
292
|
---
|
|
297
293
|
|
|
@@ -299,7 +295,7 @@ It can understand notifkit's API and help identify ad-hoc notification code in y
|
|
|
299
295
|
|
|
300
296
|
| | |
|
|
301
297
|
| :------------------ | :------------------------------------------------------------------------------------- |
|
|
302
|
-
| **Channels** | `email`, `sms`, `push`, `webhook`
|
|
298
|
+
| **Channels** | `email`, `sms`, `push`, `webhook`, `telegram`, `discord`, `whatsapp`, `slack` |
|
|
303
299
|
| **Targeting** | A user, a list of users, a segment, or a topic |
|
|
304
300
|
| **Priorities** | `low`, `normal`, `high`, `critical` — separate stream lanes |
|
|
305
301
|
| **Scheduling** | Future sends with `sendAt`, quiet-hours deferral, cancellation |
|
|
@@ -324,13 +320,18 @@ First-party packages:
|
|
|
324
320
|
|
|
325
321
|
- [`@notifkit/provider-resend`](./packages/provider-resend) — transactional email via Resend
|
|
326
322
|
- [`@notifkit/provider-fcm`](./packages/provider-fcm) — push notifications via Firebase Cloud Messaging
|
|
323
|
+
- [`@notifkit/provider-slack`](./packages/provider-slack) — Slack messages via Incoming Webhooks or the Web API
|
|
324
|
+
- [`@notifkit/provider-twilio`](./packages/provider-twilio) — SMS via Twilio, with signature-verified delivery status callbacks
|
|
325
|
+
- [`@notifkit/provider-telegram`](./packages/provider-telegram) — messages via a Telegram bot
|
|
326
|
+
- [`@notifkit/provider-discord`](./packages/provider-discord) — messages via a Discord webhook
|
|
327
|
+
- [`@notifkit/provider-whatsapp`](./packages/provider-whatsapp) — messages via Meta's WhatsApp Cloud API
|
|
327
328
|
|
|
328
329
|
For anything else, implement a simple `Transport`:
|
|
329
330
|
|
|
330
331
|
```ts
|
|
331
332
|
class MyTransport implements Transport {
|
|
332
333
|
async send(message) {
|
|
333
|
-
// Send through
|
|
334
|
+
// Send through SES, Postmark, APNs,
|
|
334
335
|
// SendGrid, a custom webhook, or anything else.
|
|
335
336
|
}
|
|
336
337
|
}
|
|
@@ -390,6 +391,13 @@ npm test
|
|
|
390
391
|
|
|
391
392
|
The test suite starts its own PostgreSQL and Redis containers, so Docker is the only thing you need running.
|
|
392
393
|
|
|
394
|
+
## Contact
|
|
395
|
+
|
|
396
|
+
Questions, bugs, or ideas — mail me. I run this on my own company, which delivers a lot of notifications daily (100K+/day).
|
|
397
|
+
|
|
398
|
+
- **Email:** [contact.devkitshq@gmail.com](mailto:contact.devkitshq@gmail.com)
|
|
399
|
+
- **Book a 30-min call:** [calendly.com/contact-devkitshq/30min](https://calendly.com/contact-devkitshq/30min)
|
|
400
|
+
|
|
393
401
|
## License
|
|
394
402
|
|
|
395
403
|
MIT. Do what you like with it, including commercially. See [LICENSE](./LICENSE).
|