home / skills / hoangnguyen0403 / agent-skills-standard / nestjs-notification

nestjs-notification skill

/skills/nestjs/nestjs-notification

This skill implements a dual-write NestJS notification system with DB persistence and FCM delivery, using granular enum types and safe error handling.

npx playbooks add skill hoangnguyen0403/agent-skills-standard --skill nestjs-notification

Review the files below or copy the command above to add this skill to your agents.

Files (3)
SKILL.md
1.8 KB
---
name: NestJS Notification System
description: Standards for defining Notification Types, Service Architecture, and FCM Integration.
metadata:
  labels: [nestjs, notification, fcm, firebase, typeorm]
  triggers:
    files: ['notification.service.ts', 'notification.entity.ts']
    keywords: [notification, push, fcm, alert, reminder]
---

# NestJS Notification Architecture

## **Priority: P0 (Standard)**

Implement a "Dual-Write" notification system: persist to Database (In-App) and send via FCM (Push).

## Structure

```text
src/modules/notification/
├── notification.service.ts   # Logic: DB Save + FCM Send
├── entities/
│   └── notification.entity.ts # DB Schema + NotificationType Enum
└── types/
    └── notification.types.ts  # Interfaces for Payloads/Metadata
```

## Implementation Guidelines

- **Use Dual-Write**: Save to DB _first_, then attempt FCM. Catch FCM errors so they don't block the logic.
- **Define Granular Types**: Use `NotificationType` Enum (e.g., `APPOINTMENT_REMINDER`) for frontend icon/color logic.
- **Stringify Metadata**: Store routing data (IDs) as JSON string in DB, but Map to string-only Key-Values for FCM `data`.
- **Handle Tokens**: Check for `fcmToken` existence before sending. Fail gracefully if missing.
- **Serialize Dates**: Convert Dates to ISO strings before sending to FCM.

## Anti-Patterns

- **No Generic Types**: Avoid `type: string`. Always use the Enum.
- **No Blocking FCM**: Never `await` FCM without a `try/catch`. It shouldn't crash the request.
- **No Complex Data in Push**: Keep FCM `data` payload flat and minimal (IDs only). Fetch details on open.

## Reference & Examples

- **Service Pattern (Dual-Write)**: [references/service.md](references/service.md)
- **Type Definitions**: [references/types.md](references/types.md)

Overview

This skill documents a NestJS Notification System standard that defines Notification Types, service architecture, and FCM integration patterns. It prescribes a dual-write approach to reliably persist in-app notifications and send push messages while avoiding common pitfalls. The goal is consistent types, safe error handling, and pragmatic payload design across backend and frontend.

How this skill works

The service performs a dual-write: it saves the notification to the database first, then attempts to send a push via FCM. Notifications use a typed NotificationType enum and a JSON stringified metadata field for routing, while FCM receives a flat data map of string-only keys and values. FCM sends are wrapped in try/catch and depend on the presence of an fcmToken; failures are logged but do not block the main request.

When to use it

  • When you need both in-app history and push delivery for the same notification event.
  • When frontend needs type-driven rendering (icons, colors, routing) based on a server enum.
  • When you must avoid request failures due to push service outages.
  • When mobile clients need minimal push payloads and fetch details on open.
  • When implementing cross-platform notifications for Android and iOS using FCM.

Best practices

  • Persist notification record before attempting FCM to ensure in-app consistency.
  • Use a strict NotificationType enum; avoid generic string types for notification classification.
  • Serialize metadata to a JSON string in DB, but map it to string-only key/value pairs for FCM data.
  • Wrap FCM calls in try/catch and never let push failures crash the request flow.
  • Check for fcmToken before sending and fail gracefully if missing.
  • Keep FCM data flat and minimal (IDs only); let the client fetch full details on open.

Example use cases

  • Appointment reminder: save an APPOINTMENT_REMINDER record, then push minimal IDs so the app loads full details on tap.
  • Order update: store ORDER_STATUS_CHANGE in DB and push orderId in FCM data for quick navigation.
  • System alert: persist ADMIN_ALERT and attempt FCM send; log errors without blocking the response.
  • Chat message notification: dual-write message metadata for in-app list and push senderId/messageId for jump-to-chat.

FAQ

Why save to DB before sending FCM?

Saving first ensures the user has a reliable in-app record even if FCM fails; it preserves state and enables retries or audits.

What should I include in the FCM data payload?

Keep it flat and minimal: string-only key/value pairs containing IDs or routing keys. Avoid large or nested objects; fetch details when the app opens.