
Security News
Ruby's Bundler 4.0.18 Extends Cooldown to bundle lock and bundle cache
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.
@sathergate/notifykit
Advanced tools
Unified notifications for Next.js. Any provider.
Send SMS, email, and push notifications through a single API. Provider-agnostic with adapters for Twilio, AWS SNS, Resend, and easy custom providers.
npm install notifykit
import { createHerald } from "notifykit";
import { createTwilioProvider } from "notifykit/adapters/twilio";
import { createResendProvider } from "notifykit/adapters/resend";
const herald = createHerald({
providers: [
createTwilioProvider({
accountSid: process.env.TWILIO_ACCOUNT_SID!,
authToken: process.env.TWILIO_AUTH_TOKEN!,
from: "+15551234567",
}),
createResendProvider({
apiKey: process.env.RESEND_API_KEY!,
from: "notifications@example.com",
}),
],
});
// Send an SMS
await herald.send({
to: "+15559876543",
channel: "sms",
body: "Your order has shipped!",
});
// Send an email
await herald.send({
to: "user@example.com",
channel: "email",
subject: "Order Confirmation",
body: "Thank you for your purchase.",
});
import { createTwilioProvider } from "notifykit/adapters/twilio";
const twilio = createTwilioProvider({
accountSid: "AC...",
authToken: "your-auth-token",
from: "+15551234567",
});
Uses the Twilio REST API directly via fetch. No SDK dependency.
import { SNSClient, PublishCommand } from "@aws-sdk/client-sns";
import { createSNSProvider } from "notifykit/adapters/sns";
const sns = createSNSProvider(
{ region: "us-east-1" },
{ SNSClient, PublishCommand },
);
You provide the AWS SDK classes. Herald stays lightweight.
import { createResendProvider } from "notifykit/adapters/resend";
const resend = createResendProvider({
apiKey: "re_...",
from: "notifications@example.com",
});
Uses the Resend REST API directly via fetch. No SDK dependency.
import type { NotificationProvider } from "notifykit";
const myProvider: NotificationProvider = {
channel: "sms",
async send(notification) {
// Your logic here
return { success: true, channel: "sms", messageId: "abc" };
},
};
Define templates with {{variable}} placeholders:
const herald = createHerald({
providers: [twilio, resend],
templates: {
"order-shipped": {
channel: "sms",
body: "Hi {{name}}, your order #{{orderId}} has shipped!",
},
"welcome-email": {
channel: "email",
subject: "Welcome, {{name}}!",
body: "Thanks for joining us, {{name}}. Get started at {{url}}.",
},
},
});
await herald.notify("order-shipped", {
to: "+15559876543",
data: { name: "Alice", orderId: "12345" },
});
import { HeraldProvider, useHerald, useNotification } from "notifykit/react";
function App() {
return (
<HeraldProvider herald={herald}>
<NotifyButton />
</HeraldProvider>
);
}
function NotifyButton() {
const { send, isSending } = useHerald();
return (
<button
disabled={isSending}
onClick={() =>
send({ to: "+15559876543", channel: "sms", body: "Hello!" })
}
>
Send SMS
</button>
);
}
function StatusAwareButton() {
const { send, status, error } = useNotification();
return (
<div>
<button
onClick={() =>
send({ to: "user@example.com", channel: "email", subject: "Hi", body: "Hello!" })
}
>
Send
</button>
{status === "sending" && <p>Sending...</p>}
{status === "sent" && <p>Sent!</p>}
{status === "error" && <p>Error: {error}</p>}
</div>
);
}
// app/api/notify/route.ts
import { createNotificationHandler } from "notifykit/next";
import { herald } from "@/lib/herald";
export const POST = createNotificationHandler(herald);
// app/api/webhooks/notifications/route.ts
import { createWebhookHandler } from "notifykit/next";
export const POST = createWebhookHandler({
verify: (request, body) => {
// Verify webhook signature
return true;
},
onStatus: async (event) => {
console.log(`Message ${event.messageId}: ${event.status}`);
},
});
Implement the NotificationProvider interface:
import type { NotificationProvider, Notification, SendResult } from "notifykit";
export function createMyProvider(config: MyConfig): NotificationProvider {
return {
channel: "sms", // or "email" or "push"
async send(notification: Notification): Promise<SendResult> {
// Send the notification using your service
return {
success: true,
channel: "sms",
messageId: "unique-id",
};
},
};
}
MIT
FAQs
Unified notifications for Next.js. Any provider.
We found that @sathergate/notifykit demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.

Security News
During a UK cyber test, a Mythos 5 agent used sockpuppets, social engineering, and prompt injection to try to get a maintainer to merge malware.

Company News
Socket is now in the AWS Security Hub Extended plan. Adopt it through AWS, apply committed spend, and block malicious open source packages.