Notify Me is a full-stack notification platform built with NestJS, React, PostgreSQL, and RabbitMQ. It centralizes multichannel delivery, scheduling, reusable templates, recipients, and delivery logs in one dashboard.
The dashboard summarizes notifications and their delivery status.
Why I Built This Project
Notification systems are common in modern products, but reliable delivery requires more than calling an email provider. I created Notify Me to study event-driven processing, multichannel delivery, resilience, scheduling, clean architecture, and complete delivery auditing.
- Event-driven architecture – Asynchronous processing through message queues.
- Multiple channels – Email, SMS, and push notification support.
- Resilience – Automatic retries, backoff, dead-letter queues, and failure handling.
- Scheduling – Notifications can be prepared for future delivery.
- Clean Architecture – Clear NestJS responsibilities and module boundaries.
- Auditing – Every stage in the notification lifecycle is recorded.
Project Architecture
The React dashboard communicates with a NestJS REST API. PostgreSQL stores users, templates, recipients, notifications, and delivery logs. RabbitMQ decouples API requests from delivery workers, allowing the HTTP layer to respond quickly while messages are processed asynchronously.
Data Flow
- The user creates or schedules a notification in the dashboard.
- The API validates and persists the request.
- A message is published to the standard or priority queue.
- A worker consumes the message and selects the appropriate provider.
- Success or failure is stored in the delivery log.
- Failed jobs are retried with backoff and eventually sent to the dead-letter queue.
Architectural Decisions
| Area | Decision | Reason |
|---|---|---|
| API | NestJS modules | Strong boundaries and dependency injection |
| Persistence | PostgreSQL + Prisma | Type-safe relational data and migrations |
| Async work | RabbitMQ | Reliable processing, priorities, retry, and DLQ |
| Front end | React + TanStack | Fast dashboard tables and server-state management |
| Authentication | JWT RS256 | Secure asymmetric token verification |
Technologies and Tools
Core Stack
- Node.js 22, TypeScript 5, and NestJS 11.
Front end
- React 19, Vite 7, Tailwind CSS 4, and React Router 7.
- TanStack Query and TanStack Table.
- shadcn/ui, Lucide React, React Hook Form, Sonner, and next-themes.
Back end
- NestJS, Prisma ORM, PostgreSQL, and RabbitMQ.
- Nodemailer for SMTP delivery.
- Passport and JWT for authentication.
- Zod for schema validation.
- Swagger and Scalar for API documentation.
Infrastructure
- Docker and Docker Compose.
- PostgreSQL 16 and RabbitMQ 3.
Features
- Email, SMS, and push notifications.
- Future delivery scheduling.
- Reusable subject and body templates per channel.
- Priority queues for urgent messages.
- Automatic retry with exponential backoff.
- Dead-letter queue for messages that exhaust retries.
- Complete success and failure audit logs.
- Recipient CRUD and bulk import.
- JWT registration and login.
- Built-in light and dark themes.
- Swagger UI and Scalar API Reference.
Reusable notification templates organized by channel.
Delivery history with status and failure information.
Queue System
notifications– Standard processing queue.notifications_priority– High-priority delivery.notifications_dlq– Failed messages that require inspection.
Notification Lifecycle
DRAFT → SCHEDULED → QUEUED → PROCESSING → SENT
└──────→ FAILED → RETRY → DLQ
Technical Challenges
1. Asynchronous Processing with RabbitMQ
The API must remain responsive even when providers are slow. Publishing a small event to RabbitMQ separates request handling from delivery and lets workers scale independently. Acknowledgements are sent only after processing, preventing message loss.
2. Clean Architecture with NestJS
Domain rules, application use cases, controllers, persistence adapters, and delivery providers are separated. Dependency injection lets tests replace infrastructure with in-memory implementations.
3. Performant Tables
TanStack Table handles sorting, pagination, filtering, and column state without rendering unnecessary rows. TanStack Query caches server state and performs targeted invalidation after mutations.
4. JWT RS256 Authentication
Tokens are signed with a private key and verified with a public key. This asymmetric approach allows services to verify access without sharing the signing secret.
What I Learned
Technical Skills
- NestJS modules, providers, guards, and interceptors.
- Prisma schemas, migrations, and queries.
- React 19, TanStack Query, and TanStack Table.
- RabbitMQ queues, exchanges, routing keys, retries, and DLQs.
- Clean Architecture, JWT RS256, Docker Compose, and accessible shadcn/ui components.
Engineering Skills
- Designing asynchronous and resilient systems.
- Selecting retry and error-handling strategies.
- Documenting APIs with Swagger, OpenAPI, and Scalar.
- Building unit and end-to-end tests with Jest.
API Endpoints
# Authentication
POST /auth/register
POST /auth/login
POST /auth/logout
# Notifications
GET /notifications
POST /notifications
DELETE /notifications/:id
# Templates
GET /templates
POST /templates
GET /templates/:id
DELETE /templates/:id
# Recipients and logs
GET /recipients
POST /recipients
DELETE /recipients/:id
GET /notification-logs
# Profile
GET /me
Available Scripts
# Back-end development and build
cd back
npm run start:dev
npm run build
npm run start:prod
# Database and tests
npx prisma migrate dev
npx prisma studio
npm test
npm run test:e2e
# Front end
cd front
npm run dev
npm run build
# Infrastructure
docker-compose up -d
docker-compose logs -f
Why This Project Matters
Notify Me demonstrates clean modular architecture, robust event-driven processing, a modern TypeScript full-stack workflow, failure recovery with retry and dead-letter queues, and a complete dashboard experience for real operational data.