Nitrofy LogoNitrofy
Como funcionaBeneficiosIntegracoesPlanosDuvidas
Comece agora
Nitrofy Logo
Comecar
Introduction
QuickstartEnvironment SetupRunning LocallyFirst Deploy
Organizations & TenancyAuthentication & SessionsRoles & PermissionsControllers & ProceduresJobs & QueuesPlugin ManagerContent LayerBuilt-in MCP ServerBillingNotificationsFile StorageEmailWebhooksAPI KeysSEOData FetchingDesign System
Development

Notifications

In-app and email notifications with templates, real-time streaming, and user preferences.

By the end of this guide, you'll understand how to implement a comprehensive notification system that delivers in-app and email notifications with real-time streaming, user preferences, and customizable templates.

Overview

The SaaS Boilerplate includes a powerful notification system that supports multiple delivery channels and provides real-time updates. Key features include:

  • Multi-channel delivery: In-app notifications and email delivery
  • Real-time streaming: Automatic UI updates when new notifications arrive
  • User preferences: Granular control over notification types and channels
  • Template system: Predefined notification types with dynamic content
  • Organization scoping: Proper data isolation for multi-tenant applications
  • Read status tracking: Mark notifications as read with bulk operations

The system integrates deeply with authentication and automatically includes notification data in user sessions for seamless access control.

Architecture

Notification Service

The core of the notification system is the NotificationService class, which orchestrates all notification operations:

// src/services/notification.ts
const notification = new NotificationService({
  context: {} as NotificationContext,
  channels: {
    'email': { /* email delivery logic */ },
    'in-app': { /* database storage logic */ }
  },
  templates: {
    USER_INVITED: { /* template definition */ },
    LEAD_CREATED: { /* template definition */ },
    // ... more templates
  }
})

Channels

Notifications can be delivered through multiple channels:

  • Email: Uses the mail service to send HTML emails with templates
  • In-app: Stores notifications in the database for UI display

Templates

Each notification type has a predefined template with:

  • Zod schema for data validation
  • Dynamic title and description functions
  • Action buttons with URLs
  • Supported channels
  • Help text for user preferences

Setting Up Notifications

Configure Notification Service

The notification service is automatically configured in src/services/notification.ts with channels and templates. It's available in the Igniter context at context.services.notification.

Use Notification Controller

The notification controller provides REST endpoints for managing notifications. Enable real-time streaming by setting stream: true in query definitions.

Configure User Preferences

Users can customize notification delivery preferences through the API endpoints. Preferences are stored in user metadata.

Notification Templates

The system includes predefined templates for common events:

Prop

Type

Template Structure

Each template defines:

USER_INVITED: {
  channels: ['email', 'in-app'],
  title: 'User Invited',
  description: 'You have been invited to join an organization',
  help: 'When a user is invited to an organization',
  action: {
    label: 'Accept',
    url: '/app/invites'
  },
  schema: z.object({
    organizationName: z.string(),
    inviterName: z.string(),
    role: z.string()
  })
}

Backend Usage (Procedures & Controllers)

Sending Notifications

Trigger notifications from your backend business logic:

// In a procedure or controller
await context.services.notification.send({
  type: 'USER_INVITED',
  data: {
    organizationName: organization.name,
    inviterName: session.user.name,
    role: invitation.role
  },
  context: {
    recipientId: invitation.email, // Send to specific user
    organizationId: organization.id
  }
})

Organization-wide Notifications

Send notifications to all members of an organization:

// Notify all organization members
await context.services.notification.send({
  type: 'LEAD_CREATED',
  data: {
    leadName: lead.name,
    leadEmail: lead.email,
    source: 'website'
  },
  context: {
    organizationId: session.organization.id // Notify all members
  }
})

Error Handling

Always wrap notification sending in error handling:

// Graceful error handling
try {
  await context.services.notification.send({
    type: 'BILLING_SUCCESS',
    data: { amount: 29.99, currency: 'USD', planName: 'Pro' },
    context: { recipientId: userId, organizationId: orgId }
  })
} catch (error) {
  // Log error but don't break main flow
  console.error('Notification failed:', error)
}

Frontend Usage (Client-side)

Listing Notifications

Retrieve paginated notifications with filtering:

// Get first page of unread notifications
const result = await api.notification.list.query({
  limit: 20,
  page: 1,
  unreadOnly: true
})

// Access pagination data
const { notifications, pagination } = result.data
console.log(`Page ${pagination.page} of ${pagination.totalPages}`)

Read Status Management

Mark notifications as read individually or in bulk:

// Mark specific notification as read
await api.notification.markAsRead.mutate({
  id: 'notif_123'
})

// Mark all notifications as read
await api.notification.markAllAsRead.mutate()
// Returns: { updatedCount: 5, message: "5 notifications marked as read" }

Unread Count

Get count of unread notifications for UI badges:

// Get unread count
const { count } = await api.notification.unreadCount.query()

// Update UI badge
updateNotificationBadge(count)

User Preferences

Manage notification delivery preferences:

// Get user preferences
const { types } = await api.notification.getUserPreferences.query()

// Update preferences
await api.notification.updateNotificationPreferences.mutate({
  preferences: {
    USER_INVITED: { inApp: true, email: false },
    LEAD_CREATED: { inApp: true, email: true }
  }
})

Real-time Streaming

Automatic Updates

Notifications support real-time streaming for instant UI updates:

// In a React component
function NotificationList() {
  const { data } = api.notification.list.useQuery({
    limit: 20,
    unreadOnly: true
  })

  // Component automatically re-renders when new notifications arrive
  return (
    <div>
      {data?.notifications.map(notification => (
        <NotificationItem key={notification.id} {...notification} />
      ))}
    </div>
  )
}

Streaming Configuration

Enable streaming in query definitions:

list: igniter.query({
  path: '/',
  stream: true, // Enables real-time updates
  use: [AuthFeatureProcedure(), NotificationProcedure()],
  handler: async ({ context, response }) => {
    // Handler returns data that gets streamed to clients
  }
})

Practical Examples

Backend: Lead Creation Notifications

Automatically notify team members when new leads are created:

// In lead creation controller/procedure
export const createLead = igniter.mutation({
  // ... other config
  handler: async ({ context, request, response }) => {
    const session = await context.auth.getSession({
      requirements: 'authenticated'
    })

    // Create the lead
    const lead = await context.database.lead.create({
      data: request.body
    })

    // Send notification to all organization members
    await context.services.notification.send({
      type: 'LEAD_CREATED',
      data: {
        leadName: lead.name,
        leadEmail: lead.email,
        source: 'website'
      },
      context: {
        organizationId: session.organization.id
      }
    })

    return response.created(lead)
  }
})

Frontend: Notification Center Component

Build a complete notification center:

function NotificationCenter() {
  const [unreadCount, setUnreadCount] = useState(0)
  const { data: notifications } = api.notification.list.useQuery({
    limit: 50,
    unreadOnly: false
  })

  // Update badge count
  useEffect(() => {
    api.notification.unreadCount.query().then(result => {
      setUnreadCount(result.data.count)
    })
  }, [])

  return (
    <div className="notification-center">
      <div className="header">
        <h3>Notifications</h3>
        <Badge count={unreadCount} />
      </div>

      <div className="notifications">
        {notifications?.data.notifications.map(notification => (
          <NotificationItem
            key={notification.id}
            notification={notification}
            onMarkAsRead={() => api.notification.markAsRead.mutate({
              id: notification.id
            })}
          />
        ))}
      </div>
    </div>
  )
}

Notification Data Structure

Notification Object

Prop

Type

Troubleshooting

Best Practices

See Also

  • Authentication & Sessions - How notifications integrate with user sessions
  • Email - Email delivery system used by notifications
  • Organizations and Tenancy - Organization-scoped notifications
  • Jobs & Queues - Background processing for bulk notifications
  • Content Layer - MDX content system for notification templates

API Reference

Notification Endpoints

Prop

Type

Billing

Subscription billing system with Stripe integration, plans, checkout, and webhooks.

File Storage

S3-compatible file storage system with secure uploads, context-based organization, and real-time progress tracking.

On this page

OverviewArchitectureNotification ServiceChannelsTemplatesSetting Up NotificationsConfigure Notification ServiceUse Notification ControllerConfigure User PreferencesNotification TemplatesTemplate StructureBackend Usage (Procedures & Controllers)Sending NotificationsOrganization-wide NotificationsError HandlingFrontend Usage (Client-side)Listing NotificationsRead Status ManagementUnread CountUser PreferencesReal-time StreamingAutomatic UpdatesStreaming ConfigurationPractical ExamplesBackend: Lead Creation NotificationsFrontend: Notification Center ComponentNotification Data StructureNotification ObjectTroubleshootingBest PracticesSee AlsoAPI ReferenceNotification Endpoints
Nitrofy LogoNitrofy

Automatize o envio e a cobrança dos seus contratos

© 2026 Nitrofy, All rights reserved