FivFold - Logo

Push Notifications Kit

Backend push notifications with device registration, sending, logging, and pluggable providers (FCM, OneSignal, AWS SNS, Pushy, Pusher Beams).

Quick reference

CLI commands

Bash
# Scaffold with defaults (NestJS + TypeORM + FCM) npx @fivfold/api add push # With explicit stack and provider npx @fivfold/api add push --framework=express --orm=prisma --provider=onesignal # Use MongoDB + Mongoose npx @fivfold/api add push --framework=nestjs --orm=mongoose --database=mongodb # Use Cosmos DB npx @fivfold/api add push --orm=cosmos-sdk --database=cosmosdb --dry-run # Dry run to preview files npx @fivfold/api add push --dry-run

Overview

The Push Notifications Kit is a backend-only module that scaffolds a complete push notification system for your Node.js application. It handles device registration, sending notifications to devices/users/topics, and optional audit logging. Unlike the Email and Kanban Kits, it does not include a frontend UI—your mobile app or PWA obtains push tokens and registers them with the backend.

The kit follows Hexagonal Architecture: a domain port (IPushNotificationService) defines the contract, and pluggable adapters implement it using third-party SDKs. You choose one provider at scaffold time (FCM, OneSignal, AWS SNS, Pushy, or Pusher Beams), and the generated code is ready to integrate with your Express or NestJS app. Supported stack combinations:

LayerOptions
FrameworkNestJS, Express
SQLTypeORM (PostgreSQL, MySQL, MariaDB, MSSQL), Prisma
NoSQLMongoose (MongoDB), Prisma (MongoDB connector)
Cloud NoSQLAzure Cosmos DB SDK, AWS DynamoDB SDK
Push ProviderFCM, OneSignal, AWS SNS, Pushy, Pusher Beams

Backend-only Kit

The Push Notifications Kit scaffolds only backend code. Your frontend (React Native, Flutter, PWA, etc.) must request notification permission, obtain a device token from the platform, and call POST /api/push/subscribe to register it. The guide below covers backend setup; frontend integration is provider-specific.

Architecture

The kit is structured in layers, with clear separation between domain logic and infrastructure:

Layer structure

1
DomainIPushNotificationService port interface and DTOs (SendNotificationDto, RegisterDeviceDto). Framework-agnostic.
2
ORMPushSubscription (device tokens per user) andPushNotificationLog (audit trail). TypeORM entities or Prisma models.
3
Framework — Express routes or NestJS controller + service. Handles HTTP, validation, and delegates to the adapter.
4
Provider adapter — Implements IPushNotificationService using the vendor SDK (e.g. FcmPushAdapter uses firebase-admin). One adapter per provider.

Swapping providers (e.g. FCM → OneSignal) requires re-scaffolding with --provider=onesignal or manually replacing the adapter file. The controller, service, and entities remain unchanged.

Supported providers

Choose one provider when scaffolding. Each has different setup requirements and capabilities:

ProviderPackageBest for
fcmfirebase-adminAndroid, iOS, Web. Free tier. Google ecosystem.
onesignalaxios (REST API)Multi-platform, easy setup, free tier.
sns@aws-sdk/client-snsAWS-native, scalable, pay-per-use.
pushypushyReliable delivery, topics, status tracking.
pusher-beams@pusher/push-notifications-serverInterests (topics), user targeting, simple API.

Guide

Step-by-step backend integration (clients obtain tokens and call your API—there is no FivFold UI kit for Push). Select framework, ORM, and push provider in the sidebar for stack-specific instructions.

The Push API module provides entities, DTOs, services, controllers/routes, and a provider adapter. Platform icons indicate your current selection.

1Install / scaffold the module

Run npx @fivfold/api init first if you haven't. The push kit requires a provider (push notification service). Select your stack and provider above, then run:

Bash
npx @fivfold/api add push

Without --provider, the CLI will prompt you to choose: FCM, OneSignal, AWS SNS, Pushy, or Pusher Beams.

2Generated file structure & wire into the app

Subsections below follow the framework and ORM from the stack sidebar (see AGENTS.md API tab §2–§3).

Generated file tree

File tree
push/ domain/ push.port.ts # IPushNotificationService interface dto/ send-notification.dto.ts register-device.dto.ts send-to-topic.dto.ts entities/ push-subscription.entity.ts notification-log.entity.ts adapters/ fcm-push.adapter.ts # Provider-specific implementation push.controller.ts # NestJS controller with all push endpoints push.service.ts # Business logic push.module.ts # NestJS module (registers entities, controller, service, adapter)

Import PushModule into AppModule

src/app.module.ts
// src/app.module.ts import { PushModule } from './modules/push/push.module'; @Module({ imports: [ TypeOrmModule.forRoot({ type: 'postgres', url: process.env.DATABASE_URL, autoLoadEntities: true, synchronize: process.env.NODE_ENV !== 'production', }), PushModule, ], }) export class AppModule {}

Add auth guard to the controller

In push.controller.ts, add your JWT guard and replace the getUser helper.

push.controller.ts
import { UseGuards } from '@nestjs/common'; import { JwtAuthGuard } from '../auth/jwt-auth.guard'; @UseGuards(JwtAuthGuard) @Controller('push') export class PushController { ... }

Run TypeORM migrations (production)

Bash
npx typeorm migration:generate src/migrations/AddPushModule -d src/data-source.ts npx typeorm migration:run -d src/data-source.ts

3API reference

REST endpoints

MethodPathDescription
POST/api/push/subscribeRegister device token for a user
DELETE/api/push/subscribe/:tokenUnregister device token
GET/api/push/subscriptionsList user's registered devices
POST/api/push/send/deviceSend notification to a specific device token
POST/api/push/send/userSend notification to all devices of a user
POST/api/push/send/topicSend notification to a topic (FCM, Pushy, Pusher Beams)

Request / response examples

Register a device (mobile app or web client calls this after obtaining a push token):

Register device
POST /api/push/subscribe Content-Type: application/json Authorization: Bearer <jwt> { "token": "fcm-or-apns-device-token-here", "platform": "ios", "metadata": { "appVersion": "1.0.0" } }

Send a notification to a user (admin or server-triggered):

Send to user
POST /api/push/send/user Content-Type: application/json Authorization: Bearer <jwt> { "userId": "user-uuid", "payload": { "title": "New message", "body": "You have a new message from John", "data": { "type": "chat", "chatId": "123" }, "imageUrl": "https://example.com/image.png" } }

Send to a topic (e.g. "news", "promotions"):

Send to topic
POST /api/push/send/topic Content-Type: application/json Authorization: Bearer <jwt> { "topic": "news", "payload": { "title": "Breaking news", "body": "Check out our latest update" } }

4Integration with frontend

You own the wiring

The step-by-step guides, environment variables, and dev-server proxy or rewrite examples are suggestions—not a mandated layout. You should read the generated files, your existing routes and auth, and your deployment topology, then choose URLs, origins, and headers that match your app. We encourage verifying every connection yourself before shipping.

Step-by-step: API ↔ browser (and ↔ UI)

This kit is backend-only: mobile and desktop clients call your API directly. Browsers and PWAs still need correct CORS when they hit a different origin than the API.

  1. Confirm routes — Ensure your Express app or Nest module exposes /api/push (or your chosen prefix). If a web UI calls same-origin /api/..., its dev server must forward to this API.
  2. CORS & clients Native apps use HTTPS to your API (no CORS). For web or admin dashboards, allow the exact browser origins that will call /api/push — not * in production.
  3. Auth context — Resolve the current user in middleware or guards and pass req.user.id (or equivalent) into Push services so list/create endpoints are scoped correctly.
  4. Response shape — The kit UI expects specific prop shapes; map your entities in the client or add a thin BFF (see UI tab and the "Connecting UI" section below).

Connecting Push data to your user system

PushSubscription (and related log rows) store a user id for each device token. That id must be the same stable identifier you use elsewhere when sending notifications after domain events.

  • Open push-subscription entity or model: align userId (or equivalent) with your User table PK or the subject you derive from JWT when registering devices.
  • When calling send-to-user endpoints, the userId in the payload should resolve to the same keys stored on subscriptions.
  • If you partition data by organization, filter subscriptions in the service layer so one admin cannot target another tenant’s users.

Inspect generated code

Open the scaffolded entities, schemas, or Prisma models for this kit and compare field names (userId, ownerId, etc.) to your User table or IdP subject. Migrate or add FKs where needed—FivFold cannot know your prior schema.

Environment variables

Examples only—replace with real secrets and URLs after reading the disclaimer above.

Database URL plus provider-specific credentials. For fcm:

.env
DATABASE_URL=postgresql://user:password@localhost:5432/yourdb FIREBASE_PROJECT_ID=your-project-id FIREBASE_CLIENT_EMAIL=firebase-adminsdk-xxx@your-project.iam.gserviceaccount.com FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"

Clients and the Push API

The Push Notifications Kit is backend-only. Your mobile app (React Native, Flutter, etc.) or web app (PWA with service worker) must implement the client side yourself:

  1. Request notification permission from the user
  2. Obtain a device token from the platform (FCM, APNs, Web Push)
  3. Call POST /api/push/subscribe with the token and platform
  4. Handle incoming notifications (foreground/background handlers)

For web push, use the Web Push API and a service worker. For mobile, use the native SDK (e.g. @react-native-firebase/messaging) to get the token, then register it with your backend.

5Third-party integrations

Provider fcm uses the vendor SDK or REST client wired in fcm-push.adapter.ts (e.g. firebase-admin for FCM, @aws-sdk/client-sns for SNS, @pusher/push-notifications-server for Pusher Beams). Inspect api/manifests/push.kit.json for the exact dependency set in this revision.

8Additional notes

Restrict who may call POST /api/push/send/*; validate userId and topics against your authorization rules. Rotate provider API keys on the same schedule as database credentials.

Domain port methods

The IPushNotificationService port defines the following methods. Provider adapters implement this interface.

MethodParametersReturnPurpose
registerDeviceuserId, dtoPromise<PushSubscription>Register device token for a user
unregisterDeviceuserId, tokenPromise<void>Unregister device token
sendToDevicetoken, payloadPromise<SendResult>Send notification to a specific device
sendToUseruserId, payloadPromise<SendResult>Send to all devices of a user
sendToTopictopic, payloadPromise<SendResult>Send to topic (FCM, Pushy, Pusher Beams)
getSubscriptionsuserIdPromise<PushSubscription[]>List user's registered devices
logNotificationsubscriptionId, messageId, status, ...Promise<void>Audit trail for sent notifications

Search docs

Search documentation by title or keywords