Define notifications in code. Store state in your database. Ship inbox, email, preferences, and unsubscribes. No platform required.
Wrong notification ID or payload shape? TypeScript error at compile time.
Memory for dev, Drizzle persistence for SQLite and Postgres.
Inbox, email, SMS, and webhook contracts. Resend, SMTP, and signed webhooks included.
Per-notification granularity. HMAC-signed unsubscribe links. RFC 8058 one-click.
Coalesce noisy sends. Hard-cap per window. Two lines of config.
useInbox(), usePreferences(), route handlers, server actions. Realtime via WebSocket.
Block real sends in development. Assert on deliveries in tests. Zero config.
Declare notifications as code. Type-safe payloads, multi-channel delivery, template interpolation.
One-line API route. Inbox, preferences, and unsubscribe endpoints handled automatically.
Trigger from anywhere in your backend. Channels, retries, and preferences resolve at runtime.
import { channel, notification, createNotifyKit } from "@notifykitjs/core"
const inbox = channel.inbox()
const email = channel.email()
export const commentMentioned = notification({
id: "comment_mentioned",
payload: { actorName: "string", postTitle: "string", postUrl: "string" },
channels: [
inbox({
title: "{{actorName}} mentioned you",
body: "In {{postTitle}}",
actionUrl: "{{postUrl}}",
}),
email({
subject: "{{actorName}} mentioned you in {{postTitle}}",
body: "Open {{postUrl}} to reply.",
}),
],
})
export const notify = createNotifyKit({
notifications: [commentMentioned] as const,
database: drizzleSqliteAdapter(db),
providers: { email: resendProvider({ apiKey, from }) },
})One send() call, multiple delivery surfaces — each respecting the recipient's preferences.
export const invite = notification({
id: "invite",
payload: { name: "string" },
channels: [inbox({ title: "{{name}} invited you" }),
email({ subject: "You're invited", body: "Open the app to respond." })],
})await notify.send({
recipientId: "user_123",
notificationId: "invite",
payload: { name: "Rey" },
})✓ Inbox → stored in your database
✓ Email → sent via Resend
✗ SMS → user opted out (preferences)