Production error monitoring via email & Telegram - Simple alternative to Sentry for small teams
npm install 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.
- ā
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
``bashFor email notifications
npm install lexakit-notifications @sendgrid/mail
Quick Start
$3
`typescript
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(),
});
`$3
`typescript
import { ErrorMonitor } from 'lexakit-notifications';const monitor = new ErrorMonitor({
notifyEmail: 'your-email@example.com',
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(),
});
`$3
`typescript
const monitor = new ErrorMonitor({
// Email configuration
notifyEmail: ['dev@example.com', 'ops@example.com'],
sendgrid: { apiKey: process.env.SENDGRID_API_KEY! },
from: {
email: 'alerts@example.com',
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);
`$3
`typescript
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: 'your-email@example.com',
sendgrid: { apiKey: process.env.SENDGRID_API_KEY! }
})
));
`Done! Now all 500+ errors will notify you via email AND Telegram.
---
š± Telegram Setup Guide
$3
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)$3
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
4. Find the "chat":{"id":123456789} in the response - that's your chat IDFor 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)$3
`typescript
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',
});
`$3
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 MyAppStatus: 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:
`typescript
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',
},
},
});
`$3
`bash
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
$3
`typescript
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;
// 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)
}
`$3
Configure different transports for different environments:
`typescript
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: 'dev@example.com', // 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: ['ops@example.com', 'cto@example.com'], // 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 |$3
For simpler use cases, use
enabledEnvironments (backwards compatible):`typescript
// Only send notifications in production
{
enabledEnvironments: ['production']
}// Send in all environments
{
enabledEnvironments: ['production', 'staging', 'development']
}
`---
Advanced Usage
$3
For custom notifications beyond error monitoring:
`typescript
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);
`$3
Send to only one transport:
`typescript
const monitor = new ErrorMonitor({
telegram: { / ... / },
sendgrid: { / ... / },
notifyEmail: 'dev@example.com',
});// 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');
`$3
`typescript
const status = await monitor.getTransportStatus();
// {
// email: { configured: true, healthy: true },
// telegram: { configured: true, healthy: true }
// }
`---
NestJS Integration
$3
`typescript
// 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: 'dev@example.com',
sendgrid: { apiKey: process.env.SENDGRID_API_KEY! }
});
app.useGlobalFilters(new ErrorMonitorFilter(errorMonitor));
`$3
`typescript
// 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: 'dev@example.com',
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',
// ...
});
}
}
`$3
`typescript
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:
$3
Throttles per status code + URL combination:
- Won't send duplicate notifications for same endpoint
- Example: 500-/api/users throttled for 5 minutes$3
Throttles per notification recipient:
- Limits total notifications per recipient
- Useful for multiple recipients with different priorities$3
Throttles per error type (4xx, 5xx):
- Groups similar errors
- Example: All 5xx errors throttled together`typescript
throttle: {
enabled: true,
window: 300000, // 5 minutes
strategy: 'per-endpoint'
}
`---
Environment Variables
`bash
Telegram
TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrsTUVwxyz
TELEGRAM_CHAT_ID=987654321Email (SendGrid)
SENDGRID_API_KEY=SG.xxxxxxxxxxxx
NOTIFY_EMAIL=dev@example.comGeneral
NODE_ENV=production
MIN_ERROR_STATUS=500
THROTTLE_WINDOW=300000
`---
API Reference
$3
`typescript
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; // Custom metadata
}
`$3
`typescript
interface NotificationResult {
success: boolean;
messageId?: string;
error?: string;
throttled?: boolean;
skipped?: boolean;
reason?: string;
transportResults?: {
email?: TransportResult;
telegram?: TransportResult;
};
}
``---
| 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 |
---
---
- [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)
---
Contributions welcome! This is the first package in the LexaKit suite of developer tools.
MIT
LexaPlus - https://lexaplus.com
Contact: parsabarati83@gmail.com
Part of the LexaKit suite - Production-ready tools for developers.
---
Made with ā¤ļø for developers who just want to know when things break.