Engineering

How we are sending notifications easy with Novu

How we are sending notifications easy with Novu

Midday is all about being on top of your business. Stay informed about your business insights, track when you get paid, receive updates on new transactions, and access general information how your business actually are doing. And that includes well-timed notifications via emails and push notifications, carefully curated for your convenience.


The challenge: Implementing a unified infrastructure for notifications

From the beginning, we knew the importance of a unified approach to managing our notifications. From past experiences of stitching together different solutions to support various notification needs, we were determined to create a system that could seamlessly support web, desktop, and mobile applications. Our goal is to ensure that our notification system can scale alongside our growth.


The solution: Novu

While we tried a bunch of different providers we decided to go with Novu based on our requirements:

  • Support Resend, Expo
  • In App notifications
  • User Preferences

Novu not only ticked every box they also got a huge bonus for being open source and you get 30K events/month for free.


Implementation and SDKs

We started with created our own package @midday/notifications where we installed @novu/node dependency, where we register our notification types for convenience:

// Our notification templates
export enum Templates {
  Transaction = "transaction",
  Transactions = "transactions",
  Inbox = "inbox",
  Match = "match",
}

// Our notification types (email|in-app)
export enum Events {
  TransactionNewInApp = "transaction_new_in_app",
  TransactionsNewInApp = "transactions_new_in_app",
  TransactionNewEmail = "transaction_new_email",
  InboxNewInApp = "inbox_new_in_app",
  MatchNewInApp = "match_in_app",
}

And using our New Transactions email as an example, which is sent from a background job using Trigger.dev when you have new transactions.

import { Notifications, Types, Events } from "@midday/notifications";

// Generate html from react-email
const html = await renderAsync(
  TransactionsEmail({
    fullName: user.full_name,
    transactions,
    locale: user.locale,
  })
);

await Notifications.trigger({
  name: Events.TransactionNewEmail,
  payload: {
    type: Types.Transaction,
    subject: t("transactions.subject"),
    html,
  },
  user: {
    subscriberId: user.id,
    teamId: team_id,
    email: user.email,
    fullName: user.full_name,
    avatarUrl: user.avatar_url,
  },
});

Because we are sending the email with the variables subject and html with the generated content we are just adding those to Novu and then we're done.


Novu - Variables


And to send In App Notifications it's just a matter of changing the Events and Types.

import { Notifications, Types, Events } from "@midday/notifications";

await Notifications.trigger({
  name: Events.TransactionNewInApp,
  payload: {
    recordId: transaction.id,
    type: Types.Transaction,
    description: t("notifications.transaction", {
      from: transaction.name,
    }),
  },
  user: {
    subscriberId: user.id,
    teamId: team_id,
    email: user.email,
    fullName: user.full_name,
    avatarUrl: user.avatar_url,
  },
});

The results: Beautiful In App Notificaitons and Emails


Midday - In App Notifications


Thanks to the SDK @novu/headless we implemented the notification center for Midday in a matter of hours to match our branding exacly like we wanted while Novu delivers the notifications in realtime.


And for user preferences we just use their API together with a simple server action.


Midday - In App Notifications


The future of Midday x Novu

We are really happy that we chose to use Novu, We have several smart notifications planned that will offer valuable business insights. Plus, Novu will integrate smoothly with our upcoming mobile app, allowing us to send push notifications effortlessly via Expo by just connecting a new provider.


GitHub

While this is just a draft on how we are using Novu in production you can dig deeper into the codebase in our repository.

PontusPontusEngineering
Stress free by midday.

Invoicing, Time tracking, File reconciliation, Storage, Financial Overview & your own
Assistant.