A powerful Telegram bot for managing multiple waitlists inside community groups, built with Telegraf, TypeScript, Prisma, and Vercel serverless functions.
- π§ Admin Management: Group admins can create and close waitlists for any user
- π₯ User Subscriptions: Members can easily subscribe/unsubscribe from waitlists
- π’ Private Broadcasting: Waitlist owners broadcast messages via DM to keep groups clean
- π Chat Isolation: Each group has completely separate waitlists and subscribers
- π€ Smart Context: Commands behave differently in groups vs DMs for optimal UX
- π Easy Tracking: List all waitlists in a group or track personal subscriptions
- π‘οΈ Secure: Only authorized users can perform sensitive operations
| Layer | Technology | Purpose |
|---|---|---|
| Telegram Bot | Telegraf | Bot interface and command handling |
| ORM | Prisma | Database schema and querying |
| Analytics | PostHog | User behavior tracking and insights |
| Runtime | ts-node | Local dev via polling |
| DB | PostgreSQL | Persistent waitlist + subscriber storage |
| Hosting | Vercel | Production webhook hosting |
elist/
βββ api/
β βββ webhook.ts # Vercel serverless function entry (webhook)
βββ prisma/
β βββ schema.prisma # Prisma data model
βββ src/
β βββ bot.ts # Bot setup and command logic
β βββ index.ts # Local development entrypoint
β βββ lib/
β βββ analytics.ts # PostHog analytics integration
β βββ prisma.ts # Prisma client setup
βββ .env # Secrets (BOT_TOKEN, DATABASE_URL, POSTHOG_API_KEY)
βββ tsconfig.json # NodeNext TypeScript config
βββ README.md # This file
βββ package.json # Scripts and dependencies
.env file contents:
# Required
BOT_TOKEN=your_telegram_bot_token
DATABASE_URL=your_postgres_connection_string
# Optional - Analytics (PostHog)
POSTHOG_API_KEY=your_posthog_api_key
POSTHOG_HOST=https://us.i.posthog.comThe bot includes comprehensive analytics tracking via PostHog. To enable:
- Sign up for PostHog (free tier available)
- Create a project and get your API key
- Add to .env:
POSTHOG_API_KEY=phc_your_project_api_key
- Choose your host (optional):
- US Cloud:
POSTHOG_HOST=https://us.i.posthog.com(default) - EU Cloud:
POSTHOG_HOST=https://eu.i.posthog.com - Self-hosted:
POSTHOG_HOST=https://your-instance.com
- US Cloud:
π Tracked Events:
- Commands: All bot commands with user and chat context
- Registrations: User DM registrations for notifications
- Subscriptions: Subscribe/unsubscribe events with product details
- Broadcasts: Message sends with delivery metrics
- Waitlists: Creation and deletion events
- Errors: Bot errors with context for debugging
π Privacy: Only user IDs, usernames, and usage metrics are tracked. No message content is logged.
| Command | Who Can Use | Description |
|---|---|---|
/start |
Anyone | Welcome message with quick start guide |
/ping |
Anyone | Check if the bot is alive |
/help |
Anyone | Show all available commands with descriptions |
| Command | Who Can Use | Description |
|---|---|---|
/openwaitlist <product> @username |
Group Admins | Create a waitlist and assign ownership |
/closewaitlist <product> |
Owner or Admins | Close and delete a waitlist permanently |
/list |
Anyone | List all waitlists in the current group |
| Command | Who Can Use | Description |
|---|---|---|
/subscribe <product> |
Anyone | Join a waitlist for a product |
/unsubscribe <product> |
Anyone | Leave a waitlist |
/mywaitlists |
Anyone | Context-aware: Shows current group's subscriptions in groups, all subscriptions in DM |
| Command | Who Can Use | Description |
|---|---|---|
/broadcast <product> <message> |
Waitlist Owner | DM only - Send message to all subscribers (keeps groups clean) |
- Each group has completely separate waitlists
- Same product names can exist in multiple groups
- No cross-group interference
- In Groups:
/mywaitlistsshows only current group's subscriptions - In DMs:
/mywaitlistsshows all subscriptions across all groups with group names - Broadcasting: Only works via DM to keep group chats clean
- Group Admins: Can create and close any waitlist
- Waitlist Owners: Can broadcast and close their own waitlists
- Regular Users: Can subscribe/unsubscribe and view lists
- All broadcasts happen via DM to bot
- Automatic message footer shows waitlist and owner info
- Group chats stay focused on discussion
- Admin adds bot to group
- Admin runs:
/openwaitlist FlowWeave @alice - Users can now:
/subscribe FlowWeave - @alice can DM bot:
/broadcast FlowWeave New feature coming soon!
- User runs:
/list(sees all group waitlists) - User runs:
/subscribe FlowWeave - User runs:
/mywaitlists(sees their subscriptions) - User receives broadcast: "New feature coming soon!\n\nYou are receiving this message because you are on the waitlist for FlowWeave by @alice"
- Admin runs:
/list(sees all waitlists with subscriber counts) - Admin can:
/closewaitlist FlowWeave(cleanup unused lists) - Owners can also close their own waitlists
pnpm install
pnpm run devThis runs src/index.ts using ts-node, and launches the bot via polling.
The bot uses a serverless webhook for production on Vercel.
import { bot } from '../src/bot.js';
export default async function handler(req, res) {
await bot.handleUpdate(req.body);
res.status(200).send('ok');
}curl "https://api.telegram.org/bot<YOUR_BOT_TOKEN>/setWebhook?url=https://<your-vercel-app>.vercel.app/api/webhook"You only need to do this once per deployed URL.
This repo is LLM-friendly. Follow these conventions:
All commands are defined like this in src/bot.ts:
bot.command('commandName', async (ctx) => { ... });You can add new commands similarly. Use ctx.chat, ctx.from, ctx.message.text for context.
-
Edit
prisma/schema.prisma -
Run:
pnpm exec prisma migrate dev --name your_migration
Send DMs:
ctx.telegram.sendMessage(userId, message);- β
ES Modules (
"type": "module"+.jsextensions) - β NodeNext resolution for compatibility
- β Strict TypeScript mode
- β Explicit command logic in one place
| Feature | Status | Notes |
|---|---|---|
/start - Welcome guide |
β | Shows comprehensive quick start |
/ping - Health check |
β | Simple pong response |
/help - Command list |
β | Complete command documentation |
/openwaitlist - Create waitlist |
β | Admin-only, assigns ownership |
/closewaitlist - Delete waitlist |
β | Owner or admin permissions |
/subscribe - Join waitlist |
β | Chat-specific, duplicate protection |
/unsubscribe - Leave waitlist |
β | Safe removal, always succeeds |
/broadcast - Send messages |
β | DM-only, automatic footer |
/list - Show group waitlists |
β | Shows names, owners, subscriber counts |
/mywaitlists - Personal view |
β | Context-aware behavior |
| Chat Isolation | β | Complete separation between groups |
| Permission System | β | Admin, owner, user roles working |
| Error Handling | β | Graceful fallbacks and clear messages |
Built by Vansh Sahay
Open to collaboration.