npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

lexakit-notifications

v1.4.0

Published

Production error monitoring via email & Telegram - Simple alternative to Sentry for small teams

Downloads

72

Readme

lexakit-notifications

Production error monitoring via email & Telegram - Simple alternative to Sentry for small teams

Get instant notifications when your Node.js/NestJS application encounters errors. Choose email, Telegram, or both. Perfect for solo developers and small teams who want simple, cost-effective error monitoring without the complexity of Sentry or Rollbar.

Note: Planning to move to @lexakit/notifications scope once the npm organization is created.

Features

  • One-line setup - Add to your app in seconds
  • 📧 Beautiful HTML emails - Professional error reports with stack traces
  • 📱 Telegram notifications - Instant alerts on your phone
  • 🚫 Smart throttling - Won't spam you on cascading failures
  • 🎯 Framework-agnostic - Works with any Node.js app or NestJS
  • 💰 Cost-effective - Use your existing services (SendGrid, Telegram)
  • 🔒 Private - Your error data stays with you
  • Lightweight - No heavy SDK, minimal performance impact
  • 🌍 Multi-transport - Email + Telegram simultaneously

Installation

# For email notifications
npm install lexakit-notifications @sendgrid/mail

# For Telegram only (no additional dependencies!)
npm install lexakit-notifications

Quick Start

Telegram Only (Simplest)

import { ErrorMonitor } from 'lexakit-notifications';

const monitor = new ErrorMonitor({
  telegram: {
    botToken: process.env.TELEGRAM_BOT_TOKEN!,
    chatId: process.env.TELEGRAM_CHAT_ID!,
  },
  appName: 'MyApp',
});

// In your error handler:
await monitor.notifyError({
  statusCode: 500,
  errorMessage: 'Database connection failed',
  url: '/api/users',
  method: 'GET',
  timestamp: new Date().toISOString(),
});

Email Only

import { ErrorMonitor } from 'lexakit-notifications';

const monitor = new ErrorMonitor({
  notifyEmail: '[email protected]',
  sendgrid: { apiKey: process.env.SENDGRID_API_KEY! }
});

await monitor.notifyError({
  statusCode: 500,
  errorMessage: 'Something went wrong',
  url: req.url,
  method: req.method,
  timestamp: new Date().toISOString(),
});

Both Email + Telegram (Recommended)

const monitor = new ErrorMonitor({
  // Email configuration
  notifyEmail: ['[email protected]', '[email protected]'],
  sendgrid: { apiKey: process.env.SENDGRID_API_KEY! },
  from: {
    email: '[email protected]',
    name: 'MyApp Alerts',
  },

  // Telegram configuration
  telegram: {
    botToken: process.env.TELEGRAM_BOT_TOKEN!,
    chatId: process.env.TELEGRAM_CHAT_ID!,
  },

  appName: 'MyApp Production',
  environment: 'production',
  enabledEnvironments: ['production', 'staging'],
});

// Errors will be sent to BOTH email and Telegram!
const result = await monitor.notifyError(errorContext);
console.log('Email result:', result.transportResults?.email);
console.log('Telegram result:', result.transportResults?.telegram);

NestJS (One-line Setup)

import { ErrorMonitor } from 'lexakit-notifications';
import { ErrorMonitorFilter } from 'lexakit-notifications/nestjs';

// In your bootstrap function:
app.useGlobalFilters(new ErrorMonitorFilter(
  new ErrorMonitor({
    telegram: {
      botToken: process.env.TELEGRAM_BOT_TOKEN!,
      chatId: process.env.TELEGRAM_CHAT_ID!,
    },
    notifyEmail: '[email protected]',
    sendgrid: { apiKey: process.env.SENDGRID_API_KEY! }
  })
));

Done! Now all 500+ errors will notify you via email AND Telegram.


📱 Telegram Setup Guide

Step 1: Create a Telegram Bot

  1. Open Telegram and search for @BotFather
  2. Send /newbot command
  3. Follow the prompts to name your bot
  4. Copy the API token (looks like 123456789:ABCdefGHIjklMNOpqrsTUVwxyz)

Step 2: Get Your Chat ID

For personal notifications:

  1. Start a chat with your new bot
  2. Send any message to the bot
  3. Visit: https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates
  4. Find the "chat":{"id":123456789} in the response - that's your chat ID

For group notifications:

  1. Add your bot to a group
  2. Send a message in the group mentioning the bot
  3. Visit the getUpdates URL (same as above)
  4. The group ID will be negative (e.g., -1001234567890)

Step 3: Configure LexaKit

const monitor = new ErrorMonitor({
  telegram: {
    botToken: '123456789:ABCdefGHIjklMNOpqrsTUVwxyz',
    chatId: '987654321', // Your personal or group chat ID
    parseMode: 'HTML',   // Optional: HTML | Markdown | MarkdownV2
    disableWebPagePreview: true,  // Optional: Don't show link previews
    disableNotification: false,   // Optional: Enable sounds
  },
  appName: 'My Production App',
});

Telegram Message Format

Errors are formatted beautifully with:

  • 🔴 Red badge for 5xx errors
  • 🟠 Orange badge for 4xx errors
  • Status code, method, URL
  • Error message with code formatting
  • Stack trace (truncated)
  • User context (ID, IP, user agent)
  • Timestamp
  • Custom metadata

Example Telegram message:

🔴 Error in MyApp

Status: 500
Method: POST
URL: /api/users/create

Error:
Database connection timeout

User: user-123
IP: 192.168.1.1

Time: 2024-01-15T10:30:00.000Z

Stack Trace:
Error: Database connection timeout
    at DatabaseService.connect...

Proxy Support (v1.4.0+)

For corporate environments behind firewalls, configure HTTP/HTTPS proxy:

const monitor = new ErrorMonitor({
  telegram: {
    botToken: process.env.TELEGRAM_BOT_TOKEN!,
    chatId: process.env.TELEGRAM_CHAT_ID!,
    // Proxy for Telegram API
    proxy: {
      url: 'http://proxy.corporate.com:8080',
      username: 'proxyuser',     // Optional
      password: 'proxypass',     // Optional
      rejectUnauthorized: true,  // SSL verification (default: true)
    },
  },
  sendgrid: {
    apiKey: process.env.SENDGRID_API_KEY!,
    // Proxy for SendGrid API
    proxy: {
      url: 'http://proxy.corporate.com:8080',
    },
  },
});

Proxy Installation

# Install optional proxy dependency
npm install https-proxy-agent

If https-proxy-agent is not installed, LexaKit will:

  1. Log a warning
  2. Attempt direct connection (may fail behind firewall)

Configuration Reference

Full Configuration

interface ErrorMonitorConfig {
  // Email Configuration
  notifyEmail?: string | string[];  // Email recipient(s)
  sendgrid?: {
    apiKey: string;
    from?: { email: string; name: string };
    proxy?: ProxyConfig;           // Proxy for SendGrid API
  };
  from?: { email: string; name: string };

  // Telegram Configuration
  telegram?: {
    botToken: string;              // Bot API token from @BotFather
    chatId: string | string[];     // Chat ID(s) to send to
    parseMode?: 'HTML' | 'Markdown' | 'MarkdownV2';
    disableWebPagePreview?: boolean;
    disableNotification?: boolean;
    botName?: string;              // For logging
    proxy?: ProxyConfig;           // Proxy for Telegram API
  };

  // General Configuration
  appName?: string;                // App name in notifications
  minStatus?: number;              // Minimum status code (default: 500)
  environment?: string;            // Current environment
  enabledEnvironments?: string[];  // Environments where notifications are sent

  // Per-Environment Configuration
  environments?: Record<string, EnvironmentTransportConfig>;

  // Throttling
  throttle?: {
    enabled: boolean;
    window: number;                // Throttle window in ms
    strategy: 'per-endpoint' | 'per-recipient' | 'per-type';
  };
}

// Proxy configuration
interface ProxyConfig {
  url: string;                     // e.g., 'http://proxy:8080'
  username?: string;               // Proxy auth username
  password?: string;               // Proxy auth password
  rejectUnauthorized?: boolean;    // SSL verification (default: true)
}

Per-Environment Transport Configuration (v1.3.0+)

Configure different transports for different environments:

const monitor = new ErrorMonitor({
  // Global transport configs
  telegram: {
    botToken: process.env.TELEGRAM_BOT_TOKEN!,
    chatId: process.env.TELEGRAM_DEV_CHAT_ID!, // Default chat
  },
  sendgrid: { apiKey: process.env.SENDGRID_API_KEY! },
  notifyEmail: '[email protected]',

  // Per-environment configuration
  environments: {
    development: { 
      telegram: true,     // ✅ Get Telegram alerts locally
      email: false,       // ❌ No email spam in dev
      consoleLog: true,   // ✅ Also log to console
    },
    staging: { 
      telegram: true, 
      email: true,
      telegramChatId: '-100staging123', // Different chat for staging
    },
    production: { 
      telegram: true, 
      email: true,
      telegramChatId: '-100prod456',    // Prod alerts chat
      notifyEmail: ['[email protected]', '[email protected]'], // More recipients
    },
  },
});

| Environment | Telegram | Email | Console | Notes | |-------------|----------|-------|---------|-------| | development | ✅ | ❌ | ✅ | Personal alerts, no email spam | | staging | ✅ | ✅ | ✅ | Team testing channel | | production | ✅ | ✅ | ✅ | Ops channel + email to leadership | | test | ❌ | ❌ | ❌ | Silent during tests |

Legacy: Simple Environment Control

For simpler use cases, use enabledEnvironments (backwards compatible):

// Only send notifications in production
{
  enabledEnvironments: ['production']
}

// Send in all environments
{
  enabledEnvironments: ['production', 'staging', 'development']
}

Advanced Usage

Using TelegramTransport Directly

For custom notifications beyond error monitoring:

import { TelegramTransport, buildTelegramAlert } from 'lexakit-notifications';

const telegram = new TelegramTransport({
  botToken: process.env.TELEGRAM_BOT_TOKEN!,
  chatId: process.env.TELEGRAM_CHAT_ID!,
});

// Check health
const isHealthy = await telegram.isHealthy();

// Get bot info
const botInfo = await telegram.getBotInfo();

// Send simple message
await telegram.sendMessage('🚀 Deployment complete! Version 1.2.3');

// Send to multiple chats
await telegram.send({
  chatId: ['chat-1', 'chat-2', 'chat-3'],
  text: '📢 System announcement',
  parseMode: 'HTML',
});

// Use helper function for alerts
const content = buildTelegramAlert(
  'High CPU Usage',
  'Server cpu-01 is at 95% CPU',
  process.env.TELEGRAM_CHAT_ID!,
  {
    emoji: '⚠️',
    fields: {
      'Server': 'cpu-01.production',
      'CPU': '95%',
      'Memory': '78%',
    },
  }
);
await telegram.send(content);

Separate Transport Methods

Send to only one transport:

const monitor = new ErrorMonitor({
  telegram: { /* ... */ },
  sendgrid: { /* ... */ },
  notifyEmail: '[email protected]',
});

// Send only to Telegram
await monitor.notifyTelegram(errorContext);

// Send only to Email
await monitor.notifyEmail(errorContext);

// Send to both (default)
await monitor.notifyError(errorContext);

// Send custom Telegram message
await monitor.sendTelegramMessage('Custom alert message');

Check Transport Status

const status = await monitor.getTransportStatus();
// {
//   email: { configured: true, healthy: true },
//   telegram: { configured: true, healthy: true }
// }

NestJS Integration

Method 1: Global Filter (Simplest)

// main.ts
import { ErrorMonitor } from 'lexakit-notifications';
import { ErrorMonitorFilter } from 'lexakit-notifications/nestjs';

const errorMonitor = new ErrorMonitor({
  telegram: {
    botToken: process.env.TELEGRAM_BOT_TOKEN!,
    chatId: process.env.TELEGRAM_CHAT_ID!,
  },
  notifyEmail: '[email protected]',
  sendgrid: { apiKey: process.env.SENDGRID_API_KEY! }
});

app.useGlobalFilters(new ErrorMonitorFilter(errorMonitor));

Method 2: Module with Dependency Injection

// app.module.ts
import { LexaKitNotificationsModule } from 'lexakit-notifications/nestjs';

@Module({
  imports: [
    LexaKitNotificationsModule.forRoot({
      telegram: {
        botToken: process.env.TELEGRAM_BOT_TOKEN!,
        chatId: process.env.TELEGRAM_CHAT_ID!,
      },
      notifyEmail: '[email protected]',
      sendgrid: { apiKey: process.env.SENDGRID_API_KEY! }
    })
  ]
})
export class AppModule {}

// Inject anywhere:
@Injectable()
export class MyService {
  constructor(private notifications: LexaKitNotificationsService) {}
  
  async someMethod() {
    await this.notifications.notifyError({
      statusCode: 500,
      errorMessage: 'Something went wrong',
      // ...
    });
  }
}

Method 3: Async Configuration

import { LexaKitNotificationsModule } from 'lexakit-notifications/nestjs';
import { ConfigModule, ConfigService } from '@nestjs/config';

@Module({
  imports: [
    LexaKitNotificationsModule.forRootAsync({
      imports: [ConfigModule],
      useFactory: (config: ConfigService) => ({
        telegram: {
          botToken: config.get('TELEGRAM_BOT_TOKEN'),
          chatId: config.get('TELEGRAM_CHAT_ID'),
        },
        notifyEmail: config.get('NOTIFY_EMAIL'),
        sendgrid: {
          apiKey: config.get('SENDGRID_API_KEY')
        }
      }),
      inject: [ConfigService]
    })
  ]
})
export class AppModule {}

Throttling Strategies

Prevent notification spam during cascading failures:

per-endpoint (default)

Throttles per status code + URL combination:

  • Won't send duplicate notifications for same endpoint
  • Example: 500-/api/users throttled for 5 minutes

per-recipient

Throttles per notification recipient:

  • Limits total notifications per recipient
  • Useful for multiple recipients with different priorities

per-type

Throttles per error type (4xx, 5xx):

  • Groups similar errors
  • Example: All 5xx errors throttled together
throttle: {
  enabled: true,
  window: 300000,  // 5 minutes
  strategy: 'per-endpoint'
}

Environment Variables

# Telegram
TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrsTUVwxyz
TELEGRAM_CHAT_ID=987654321

# Email (SendGrid)
SENDGRID_API_KEY=SG.xxxxxxxxxxxx
[email protected]

# General
NODE_ENV=production
MIN_ERROR_STATUS=500
THROTTLE_WINDOW=300000

API Reference

ErrorContext

interface ErrorContext {
  method: string;          // HTTP method
  url: string;             // Request URL
  statusCode: number;      // HTTP status
  errorMessage: string;    // Error message
  stack?: string;          // Stack trace
  userId?: string;         // User ID (if available)
  timestamp: string;       // ISO timestamp
  ipAddress?: string;      // Client IP
  userAgent?: string;      // User agent
  metadata?: Record<string, any>;  // Custom metadata
}

NotificationResult

interface NotificationResult {
  success: boolean;
  messageId?: string;
  error?: string;
  throttled?: boolean;
  skipped?: boolean;
  reason?: string;
  transportResults?: {
    email?: TransportResult;
    telegram?: TransportResult;
  };
}

Comparison with Sentry

| Feature | lexakit-notifications | Sentry | |---------|----------------------|--------| | Cost | Free (just email/Telegram) | $26+/month | | Setup | One line of code | SDK integration + config | | Data Privacy | Your servers only | Third-party service | | Email Alerts | ✅ Built-in, beautiful | Requires configuration | | Telegram Alerts | ✅ Built-in | Requires integration | | Performance Monitoring | ❌ | ✅ | | Issue Tracking | ❌ (use email/Telegram) | ✅ | | Team Collaboration | ✅ (via email/Telegram) | ✅ (dashboard) | | Best For | Small teams, side projects | Large teams, enterprise |


Use Cases

Solo Developers

  • Quick error alerts without setting up monitoring infrastructure
  • Free Telegram notifications to your phone
  • No credit card required

Small Startups

  • Cost-effective alternative to $29/mo Sentry plans
  • Email + Telegram alerts reach the whole team instantly

Side Projects

  • Know when things break without checking logs
  • Mobile notifications via Telegram

Internal Tools

  • Simple monitoring for admin dashboards
  • Keep error data private

Roadmap

  • [x] Telegram bot notifications
  • [x] Multi-transport support (email + Telegram)
  • [ ] Slack webhook support
  • [ ] Discord webhook support
  • [ ] Error grouping and deduplication
  • [ ] Custom email/message templates
  • [ ] Error frequency reports (daily/weekly digest)

Contributing

Contributions welcome! This is the first package in the LexaKit suite of developer tools.

License

MIT

Author

LexaPlus - https://lexaplus.com
Contact: [email protected]

Part of the LexaKit suite - Production-ready tools for developers.


Made with ❤️ for developers who just want to know when things break.