Getting Started Guide
Table of Contents
Cloud Native Notifications Library
Airhorn makes it easy to send SMS, SMTP, Webhooks, and mobile push notifications easily using templates through your standard cloud providers. We focused on making it cloud native by default (using cloud services).
Features
- Supports multiple notification types: SMS, Email, Mobile Push, Webhooks
- A unified API for all notification types using the
send()method. - Powerful Hooks system (
BeforeSend,AfterSend) for intercepting and modifying messages with full parameter access. - Event Emitting built in by default for extendability and observability.
- Send Strategy (Round Robin, Fail Over, All) Choose the best delivery method for each notification.
- Built in Webhook support for sending notifications to external services.
- Built in support for retries and error handling on sends.
- Advanced caching on template compilation and execution.
- Load a template from a file for easy GitOps based workflows.
- Many supported providers such as Twilio (with Sendgrid), AWS, and Google Cloud.
- Robust (6+ template formats) templating via ecto
- Easily build your own provider with minimal effort via
AirhornProviderinterface. - Statistics tracking for send successes, failures, and execution times (instance only).
- ESM and Typescript based supporting Nodejs 20+
- Maintained on a regular basis with updates and improvements.
Getting Started
To get started with Airhorn, you can install the package via npm:
npm install airhorn @airhornjs/twilio
import { Airhorn, AirhornProviderType } from "airhorn";
import { AirhornTwilio } from "@airhornjs/twilio";
const providers = [
new AirhornTwilio({
accountSid: "your_account_sid",
authToken: "your_auth_token"
}),
];
const airhorn = new Airhorn({
providers
});
// this will give you twilio and webhook (built in) support. Now lets create a template and send it!
const template = {
from: "+12223334444",
content: "Hey <%= name %> this is a test message from Airhorn",
templateEngine: "ejs",
}
const data = { name: "John" };
await airhorn.send("+1234567890", template, data, AirhornProviderType.SMS);
Check out the documentation and providers to learn more!
Hooks
Airhorn provides a powerful hook system that allows you to intercept and modify notifications before and after they are sent. This enables custom validation, logging, transformation, and post-processing of messages.
Available Hooks
- BeforeSend: Called after template rendering but before the message is sent to providers
- AfterSend: Called after the message has been sent and providers have responded
BeforeSend Hook
The BeforeSend hook receives the rendered message and options, allowing you to modify them before sending:
import { Airhorn, AirhornHook } from "airhorn";
const airhorn = new Airhorn();
// Add a hook to modify message content before sending
airhorn.addHook(AirhornHook.BeforeSend, ({ message, options }) => {
// Add a prefix to all messages
message.content = `[IMPORTANT] ${message.content}`;
// Modify the recipient
if (message.to.includes("test")) {
message.to = "[email protected]";
}
// Log the outgoing message
console.log("Sending message:", message);
});
AfterSend Hook
The AfterSend hook receives the complete result object after sending, allowing you to post-process or enrich the result:
// Add a hook to track results after sending
airhorn.addHook(AirhornHook.AfterSend, ({ result }) => {
// Add custom metadata
result.metadata = {
processedAt: new Date(),
environment: process.env.NODE_ENV
};
// Send to analytics
if (result.success) {
analytics.track("notification_sent", {
type: result.message?.type,
provider: result.providers[0]?.name
});
}
// Log failures
if (!result.success) {
logger.error("Notification failed", result.errors);
}
});
Multiple Hooks
You can register multiple hooks of the same type, and they will execute in the order they were registered:
// First hook: validation
airhorn.addHook(AirhornHook.BeforeSend, ({ message }) => {
if (!message.content || message.content.length === 0) {
throw new Error("Message content cannot be empty");
}
});
// Second hook: sanitization
airhorn.addHook(AirhornHook.BeforeSend, ({ message }) => {
message.content = sanitizeHtml(message.content);
});
// Third hook: logging
airhorn.addHook(AirhornHook.BeforeSend, ({ message }) => {
logger.info("Sending notification", { to: message.to, type: message.type });
});
Hook Error Handling
By default, hook errors are caught and handled gracefully. You can configure Airhorn to throw hook errors by setting throwOnErrors:
const airhorn = new Airhorn({ throwOnErrors: true });
airhorn.addHook(AirhornHook.BeforeSend, ({ message }) => {
// This error will now throw and stop execution
throw new Error("Validation failed");
});
Providers
We currently support multiple providers and you can easily add more by following the AirhornProvider interface. Here are the supported providers:
We currently support twilio, aws, and azure with thier offerings. Here is a chart showing what functionality is in each:
| Provider | SMS | Push | Webhook | |
|---|---|---|---|---|
(built in airhorn) |
❌ | ❌ | ❌ | ✅ |
@airhornjs/twilio |
✅ | ✅ | ❌ | ❌ |
@airhornjs/aws |
✅ | ✅ | ✅ | ❌ |
@airhornjs/azure |
✅ | ✅ | ✅ | ❌ |
Note: We used to support firebase because of mobile push but it made more sense to focus on aws and azure because it is more comprehensive.
How to Contribute
Now that you've set up your workspace, you're ready to contribute changes to the airhorn repository you can refer to the CONTRIBUTING guide. If you have any questions please feel free to ask by creating an issue and label it question.
Licensing and Copyright
This project is MIT License © Jared Wray