Most chat widgets ship with their own dashboard. And another dashboard for email. And a third for the messaging app your users actually use. If you're an indie maker with 30 signups, opening three dashboards to reply to five messages is a joke.
We built Knocket as the free contact layer for indie developers who don't want to babysit dashboards. One line to install a live chat widget. One shareable contact page. One inbox that receives Live Chat, Telegram, and Email in the same place — and lets you reply directly from Telegram without opening anything else.
This post walks through the design decisions behind the unified inbox — specifically how we route three channels through a single webhook without leaking channel-specific logic all over the codebase.
The problem with "one inbox for everything"
You've seen the pitch before. Every helpdesk product from Intercom on down claims a "unified inbox." In practice they mean:
- Live chat: real-time bidirectional WebSocket
- Email: SMTP inbound + polling
- Messaging apps: platform-specific webhooks (Telegram Bot API, Meta Graph, etc.)
Each channel has its own delivery guarantees, ordering, retry semantics, and failure modes. A naive implementation hardcodes three code paths and inevitably drifts — a bug fix in the email path doesn't apply to Telegram, and now you have three subtly different reply behaviors.
The design: normalize at the edge, unify in the middle
We settled on a three-layer shape:
┌────────────────────────────────────────────┐
│ Channel Adapters (one per source) │
│ ─ Live Chat WebSocket │
│ ─ Telegram Bot webhook │
│ ─ IMAP/SMTP email │
└────────────────────────────────────────────┘
↓ normalized event
┌────────────────────────────────────────────┐
│ Unified Message Bus (single format) │
│ { conversation_id, sender, body, ... } │
└────────────────────────────────────────────┘
↓ fan-out
┌────────────────────────────────────────────┐
│ Inbox UI · Notifications · Reply Router│
└────────────────────────────────────────────┘
The core rule: anything that knows about "Telegram" or "SMTP" lives only in an adapter. The bus and the UI see one message shape. Adding a new channel (WhatsApp is next) is a new adapter, not a new special case in the reply logic.
The reply router — the interesting part
The subtle problem: when you reply from Telegram, the reply must go back to the visitor via the original channel. If Sarah pinged you via the website widget and you type a reply into your Telegram app, that reply has to appear in Sarah's browser — not as a Telegram message to Sarah.
Every message on the bus carries source_channel. The reply router reads that field and dispatches to the right outbound adapter:
// Simplified
async function routeReply(originalMessage, replyBody) {
const adapter = adapters[originalMessage.source_channel];
await adapter.sendReply({
conversation_id: originalMessage.conversation_id,
body: replyBody,
});
}
The Telegram adapter is where the neat trick lives: when Knocket forwards a live-chat message to your Telegram, the message includes structured metadata so a quote-reply in Telegram carries enough context for the router to reconstruct the original conversation. You reply in Telegram like you're replying to a friend, and it lands in the visitor's browser.
No new dashboard. No context switch. No "let me open the console real quick."
What this made easy
- New channels are additive. Adding a channel is one adapter file plus registration.
- The inbox UI is boring. It renders one message shape. It doesn't care about the source.
- Notifications are trivial. One "new message" event, delivered to browser push and Telegram.
- Failure modes are localized. If Telegram's API is down, only the Telegram adapter fails. Live chat and email keep flowing.
What we open-sourced
We also released a companion project — an open-source AI auto-reply agent that plugs into the same message bus. It's a reference implementation for anyone who wants to run their own AI reply layer against a Knocket inbox: github.com/fangxinmoon/knocket-inbox-agent-EN
If you want to plug it into your own knowledge base, the agent's system prompt and retrieval layer are yours to swap out.
Try it
Knocket is 100% free forever — no ads, no seat limits, no paid tier. If you're at the "first 100 users" stage and Intercom's pricing feels absurd, this is the tool we wish existed when we started.
Set-up is one script tag. If you're on Framer, Webflow, WordPress, Ghost, Shopify, or anything else that supports custom code, you're 60 seconds from a live chat widget.
Powered by Tencent RTC infrastructure for global low-latency delivery.
Would love feedback in the comments — especially from anyone who's built or hated multi-channel inboxes before. What did we get wrong?
Top comments (0)