Notifo: a multi-channel notification service with topic subscriptions
Multi channel notification service for collaboration tools, e-commerce, news service and more.
At a glance
- What is it?
- Notifo is a C# notification service that turns topic subscriptions into messages across email, SMS, mobile push, chat, web, web push and webhooks, with a management UI, MJML and Liquid email templates, and an embeddable JavaScript overlay. You run it with Docker Compose, and before you let anyone else near it you have to replace the web push key pair and the social login credentials that ship in the repository.
- Who is it for?
- Notifo suits an application that needs to tell its users things across several channels and wants one subscription model rather than one integration per channel, and that is willing to run the service itself. It does not suit a project that only needs email, since the abstraction and the queue machinery are more than that use requires, and it is not a hosted service you can sign up for without reading the self-hosting notes.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 33 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One subscription model, seven kinds of channel
Notifo is a multi-channel notification service for collaboration tools, e-commerce, news, magazines and anybody who wants to notify their users, and the channel table is the clearest statement of what it does. Email goes out through SMTP, Amazon SES, Mailjet or Mailchimp. SMS through Twilio, MessageBird, Seven or Telekom. Mobile push through Firebase. Messaging through Telegram, Discord, Threema or WhatsApp via MessageBird. Web through SignalR or WebSockets with polling as a fallback. Web push is built in using VAPID. Webhooks are any HTTP endpoint. Two details are easy to miss. The web channel has polling as a fallback, so a client behind a proxy that blocks sockets still gets notifications, and the web push implementation is built in rather than delegated to a provider. There is also a quirk documented in a note: Telekom sends SMS but currently lists itself under Messaging in the management UI, so you look for it there. More providers can be added without touching this repository, through a separate OpenNotifications project.
Topics, paths and the matching that produces a user event
The model has three moving parts and the documentation is unusually clear about who owns what. Users subscribe to topics defined by a path such as clothes/shoes/nike, and providing a good interface for that subscription is your job, not Notifo's. Your backend creates events using very specific topic paths, for example clothes/shoes/nike/<model>. Notifo then creates user events based on the matching subscriptions, where a subscription is either for a specific path or for a parent path as in the example, and each subscription carries its own individual notification preferences. The worked example in the readme makes the point: in a task management system you can automatically subscribe users to a project, for example project/123, with a preference for web notifications only, and when a user manually subscribes to a specific task, for example project/123/tasks/abc, that subscription can carry a preference to also send emails. Queues and schedulers are responsible for sending the notifications once they have not been confirmed.
Confirmation preferences are how it avoids spamming you
This is the feature that makes the service more than a fan-out, and it is worth understanding before you design your event types. Notifications can have a confirmation preference with three values, None, Explicit and Seen. Only unconfirmed notifications are sent through a channel, and you can configure a delay before sending. The consequence is that a user does not receive a notification when they have already explicitly confirmed it in Explicit mode, or have seen it in Seen mode. The readme states the purpose plainly: this avoids spamming your users with notifications they no longer need, and it lets you track who has seen or confirmed urgent and important notifications. That tracking is part of the feature list too, which claims the service tracks which notification has been delivered, seen or confirmed. A scheduler is therefore doing real work rather than just delaying a send, since the decision to send depends on what the recipient did in the meantime.
Running it, and the two secrets you have to replace
The published Docker image is on Docker Hub, and the fastest path is the Compose setup in the deployment directory:
cd deployment/docker-composeYou set NOTIFO_DOMAIN in the env file and then start the stack:
docker compose up -dAfter that you open the domain and create the first administrator account. The warning is the important part, and the readme puts it in bold: before anyone else uses the instance, read the Before you go live section, because the shipped defaults include a web push key pair that is public in this repository and social login credentials that belong to notifo.io. That is a genuine hazard rather than a formality. A public VAPID key pair means anyone who has read the repository can send web push messages attributed to your instance, and social login credentials that belong to the vendor means your instance is wired to the vendor's identity provider until you change them. The self-hosting documentation covers the requirements, Docker Compose, TLS, the secrets you must replace, and backups and upgrades, and the configuration documentation covers every setting that matters, how environment variables map to it, and which combinations are not allowed.
Configuration is appsettings.json with a double underscore convention
Everything in the appsettings.json can be set with an environment variable, and the mapping is mechanical: the path segments are joined with a doubled low line. The storage section in the settings file looks like this:
"storage": {
"mongoDB": {
"connectionString": "mongodb://localhost"
}
}and the environment variable that sets the same thing is:
STORAGE__MONGODB__CONNECTIONSTRING=mongodb://localhostSo the section name becomes the first segment, the subsection the second, and the key the last, with the key uppercased. The documentation for configuration is worth reading in full because it also lists the combinations that are rejected at startup, which means a misconfiguration fails loudly rather than half-working. The Docker build uses the same convention, with build arguments named NOTIFO__BUILD__VERSION and a runtime argument NOTIFO__RUNTIME__VERSION, so the mechanism is consistent across the deployment and the image build. The backend itself is ASP.NET Core on .NET 10, with MongoDB as the primary store and MySQL, PostgreSQL or SQL Server through Entity Framework as alternatives, OpenID Connect via OpenIddict, SignalR for web sockets and optional Redis for clustering.
The email templates and the frontend stack
The management UI covers notification templates, users, subscriptions, apps, settings and email templates, and the email templates support both MJML and Liquid. That pairing is the interesting choice, since MJML is a markup language for responsive HTML email and Liquid is a general purpose template engine, so a team can use whichever fits the template they are writing. The rest of the front end stack is React with Redux Toolkit and React Router, TypeScript built with Vite, and Bootstrap with custom Sass carrying the Argon Design theme. The feature list also includes rich notifications with a lot of formatting options such as small and large images, an embeddable JavaScript SDK that adds a notification overlay to your web application, and reliable delivery through retry mechanisms and message queues for all notifications and channels. The API reference of a running instance is generated from an OpenAPI document and served at the api docs path, so the reference matches the deployment rather than a hand-written document that drifts.
Editorial conclusion
Notifo suits an application that needs to tell its users things across several channels and wants one subscription model rather than one integration per channel, and that is willing to run the service itself. It does not suit a project that only needs email, since the abstraction and the queue machinery are more than that use requires, and it is not a hosted service you can sign up for without reading the self-hosting notes. Before you go live, replace the shipped web push key pair and the social login credentials that belong to notifo.io, set the domain in the env file, and read the configuration documentation for the combinations that are rejected at startup.
Frequently asked questions
Which notification channels does Notifo support?
Email through SMTP, Amazon SES, Mailjet and Mailchimp, SMS through Twilio, MessageBird, Seven and Telekom, mobile push through Firebase, messaging through Telegram, Discord, Threema and WhatsApp via MessageBird, web through SignalR or WebSockets with polling as a fallback, web push built in using VAPID, and webhooks to any HTTP endpoint. More providers can be added through the separate OpenNotifications project.
How do I run Notifo myself?
Use the Compose setup in the deployment directory. Set NOTIFO_DOMAIN in the env file, run docker compose up -d, then open the domain and create the first administrator account. A published Docker image is also available on Docker Hub.
What must I change before opening a Notifo instance to users?
The shipped defaults include a web push key pair that is public in the repository and social login credentials that belong to notifo.io, so both have to be replaced. The readme points at the Before you go live section of the self-hosting documentation, which also covers TLS, backups and upgrades.
How does Notifo decide whether to send a notification?
Notifications can carry a confirmation preference of None, Explicit or Seen, and only unconfirmed notifications are sent through a channel, with a configurable delay. In Explicit mode a notification the user has already confirmed is not sent, and in Seen mode one they have already seen is not sent, which is what keeps the service from spamming users.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/notifo-io-notifo)Was this useful?