A lightweight Next.js package for sending notifications to Telegram. Perfect for contact forms, bug reports, user feedback, and any notification needs.
- π Simple Integration - Get started in under 5 minutes
- π Secure - Server-side Telegram API integration
- π TypeScript - Full type safety out of the box
- π¨ Flexible - Works with any form library or custom UI
- π File Support - Send documents, images, and attachments
- β‘ Lightweight - Minimal dependencies, < 20KB gzipped
- π Auto Retry - Built-in retry logic with exponential backoff
- π― Generic - Not limited to forms - works for any notification scenario
npm install nextjs-telegram-notifyyarn add nextjs-telegram-notifypnpm add nextjs-telegram-notify- Create a bot via @BotFather on Telegram
- Get your bot token
- Get your chat ID using @userinfobot or @getidsbot
Create a .env.local file in your Next.js project:
TELEGRAM_BOT_TOKEN=your_bot_token_here
TELEGRAM_CHAT_ID=your_chat_id_hereCreate app/api/telegram-notify/route.ts:
// For default setup - just one line!
export { POST } from 'nextjs-telegram-notify/route';'use client';
import { useTelegramNotify } from 'nextjs-telegram-notify';
export default function ContactForm() {
const { send, loading, error } = useTelegramNotify();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
await send({
message: 'New contact form submission!',
parseMode: 'HTML'
});
};
return (
<form onSubmit={handleSubmit}>
<button disabled={loading}>
{loading ? 'Sending...' : 'Submit'}
</button>
{error && <p>Error: {error.message}</p>}
</form>
);
}That's it! π
'use client';
import { useTelegramNotify } from 'nextjs-telegram-notify';
import { useState } from 'react';
export default function ContactForm() {
const { send, loading, error, success } = useTelegramNotify();
const [formData, setFormData] = useState({
name: '',
email: '',
message: ''
});
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
const message = `
π¬ <b>New Contact Form Submission</b>
π€ Name: ${formData.name}
π§ Email: ${formData.email}
π¬ Message: ${formData.message}
${new Date().toLocaleString()}
`.trim();
await send({ message, parseMode: 'HTML' });
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
placeholder="Name"
required
/>
<input
type="email"
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
placeholder="Email"
required
/>
<textarea
value={formData.message}
onChange={(e) => setFormData({ ...formData, message: e.target.value })}
placeholder="Message"
required
/>
<button type="submit" disabled={loading}>
{loading ? 'Sending...' : 'Send Message'}
</button>
{error && <p className="error">{error.message}</p>}
{success && <p className="success">Message sent successfully!</p>}
</form>
);
}'use client';
import { useTelegramNotify } from 'nextjs-telegram-notify';
export default function BugReportButton() {
const { send, loading } = useTelegramNotify();
const reportBug = async () => {
await send({
message: `
π <b>Bug Report</b>
π Page: ${window.location.href}
π₯οΈ User Agent: ${navigator.userAgent}
β° Time: ${new Date().toISOString()}
`.trim(),
parseMode: 'HTML'
});
};
return (
<button onClick={reportBug} disabled={loading}>
π Report Bug
</button>
);
}'use client';
import { useTelegramNotify } from 'nextjs-telegram-notify';
export default function FileUploadForm() {
const { send, loading } = useTelegramNotify();
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const file = formData.get('file') as File;
await send({
message: 'π New file uploaded',
files: [file]
});
};
return (
<form onSubmit={handleSubmit}>
<input type="file" name="file" required />
<button type="submit" disabled={loading}>Upload</button>
</form>
);
}// app/api/feedback/route.ts
import { sendTelegramNotification } from 'nextjs-telegram-notify/server';
export async function POST(request: Request) {
const { rating, comment } = await request.json();
await sendTelegramNotification({
message: `
β <b>User Feedback</b>
Rating: ${'β'.repeat(rating)}
Comment: ${comment}
`.trim(),
parseMode: 'HTML'
});
return Response.json({ success: true });
}Protect your API endpoint from abuse with built-in rate limiting:
import { createTelegramRoute } from 'nextjs-telegram-notify/route';
export const POST = createTelegramRoute({
rateLimit: {
maxRequests: 10, // Max requests per window
windowMs: 60000, // Time window in milliseconds (1 minute)
}
});Default Limits:
- Per-IP: 20 requests per minute
- Global (Telegram API): 30 requests per second
Rate Limit Headers:
X-RateLimit-Limit: 20
X-RateLimit-Remaining: 15
X-RateLimit-Reset: 1234567890
Disable Rate Limiting:
export const POST = createTelegramRoute({
rateLimit: false
});Control which origins can access your API:
export const POST = createTelegramRoute({
cors: {
origin: 'https://yourdomain.com', // Specific origin
methods: ['POST', 'OPTIONS'],
allowedHeaders: ['Content-Type'],
credentials: false,
}
});Multiple Origins:
cors: {
origin: ['https://yourdomain.com', 'https://app.yourdomain.com'],
}Wildcard (Development Only):
cors: {
origin: '*', // Allow all origins - not recommended for production
}Disable CORS:
export const POST = createTelegramRoute({
cors: false
});- Always use environment variables for sensitive data
- Enable rate limiting to prevent abuse
- Restrict CORS to your domain only
- Use lifecycle hooks for logging and monitoring
- Validate input on the server side
Complete Security Example:
// app/api/telegram-notify/route.ts
import { createTelegramRoute } from 'nextjs-telegram-notify/route';
export const POST = createTelegramRoute({
// Rate limiting
rateLimit: {
maxRequests: 10,
windowMs: 60000,
},
// CORS protection
cors: {
origin: process.env.NEXT_PUBLIC_APP_URL!,
credentials: false,
},
// Logging
onBeforeSend: async (request) => {
console.log('Notification request:', {
timestamp: new Date().toISOString(),
messageLength: request.message.length,
});
},
// Error tracking
onError: async (error) => {
console.error('Notification failed:', error);
// Report to your error tracking service
},
});Client-side React hook for sending notifications.
Parameters:
config(optional):endpoint?: string- API endpoint (default:/api/telegram-notify)onSuccess?: () => void- Success callbackonError?: (error: Error) => void- Error callback
Returns:
send: (options: NotifyOptions) => Promise<void>- Send notification functionloading: boolean- Loading stateerror: Error | null- Error statesuccess: boolean- Success statereset: () => void- Reset state function
Server-side function for sending notifications.
Parameters:
options: NotifyOptions:message: string- Message text (required)parseMode?: 'HTML' | 'Markdown' | 'MarkdownV2'- Message formattingfiles?: FileAttachment[]- File attachmentschatId?: string- Override default chat IDdisableNotification?: boolean- Silent notificationthreadId?: number- Forum topic thread ID
import {
formatMessageWithTimestamp,
escapeHtml,
escapeMarkdown,
validateFileSize,
validateFileType,
formatFormData,
createNotification
} from 'nextjs-telegram-notify';Helper for creating structured notification messages:
const message = createNotification({
title: 'New Order',
emoji: 'π',
fields: {
'Order ID': '#12345',
'Customer': 'John Doe',
'Total': '$99.99'
},
includeTimestamp: true
});await send({
message: `
<b>Bold text</b>
<i>Italic text</i>
<code>Code</code>
<a href="https://example.com">Link</a>
`.trim(),
parseMode: 'HTML'
});await send({
message: `
**Bold text**
_Italic text_
\`Code\`
[Link](https://example.com)
`.trim(),
parseMode: 'Markdown'
});- Never expose your bot token - Keep it in server-side environment variables
- Validate user input - Sanitize data before sending to Telegram
- Implement rate limiting - Prevent spam/abuse of your notification endpoint
- Use CAPTCHA - For public-facing forms to prevent bot submissions
- Validate file uploads - Check file types and sizes before sending
// app/api/telegram-notify/route.ts
import { createTelegramRoute } from 'nextjs-telegram-notify/route';
export const POST = createTelegramRoute({
onBeforeSend: async (request) => {
// Add custom validation, logging, etc.
console.log('Sending notification:', request.message);
},
onAfterSend: async (request) => {
// Log success, trigger webhooks, etc.
console.log('Notification sent successfully');
},
onError: async (error, request) => {
// Custom error handling
console.error('Failed to send notification:', error);
}
});import { createTelegramClient } from 'nextjs-telegram-notify/server';
const client = createTelegramClient({
botToken: process.env.TELEGRAM_BOT_TOKEN!,
chatId: process.env.TELEGRAM_CHAT_ID!
});
await client.sendMessage('Custom message');
await client.sendDocument(fileAttachment, {
caption: 'File caption'
});- β Contact forms
- β Bug reports
- β Typo corrections
- β User feedback & ratings
- β Newsletter signups
- β Order notifications
- β Support tickets
- β System alerts
- β Analytics events
- β Content moderation alerts
Contributions are welcome! Please feel free to submit a Pull Request.
MIT Β© Muhammad Abdugafarov
Built with β€οΈ for the Next.js community.
Need help? Open an issue on GitHub