Building a live-chat widget: real-time WebSockets, one script tag
How I built an embeddable live-chat widget: real-time messaging over WebSockets with Django Channels, a Shadow-DOM widget, and AI-assisted replies.

I'd built plenty of features over the years, but I'd never actually built real-time. So I set out to learn WebSockets properly — by shipping something real: an embeddable live-chat widget in the Intercom / Crisp / Tawk.to mould, open source and self-hostable.
What it does
A site owner drops one script tag on any page and a chat widget appears. Visitors chat in real time with an operator who replies from a dashboard. Around that core it does typing indicators, online/away presence, pre-chat forms, canned responses, an AI “Suggest a reply” button, post-chat ratings, and branded email transcripts — all multi-tenant, so one deployment serves many sites.
How it's built
The backend is Django with Channels running over ASGI (Daphne), and a Redis channel layer fanning messages out across connections — that's what makes it genuinely real-time rather than polled. Both ends are WebSocket clients: the embedded widget and the operator inbox. The widget itself is dependency-free vanilla JS rendered inside a Shadow DOM, so it can never clash with the host page's CSS, and it's driven by a single site key. AI drafts stream token-by-token from Claude over the same operator socket.
One concept per phase
I built it deploy-first and in thin slices — one new concept per phase, live on a real URL before adding the next. Phase 0 was just an echo over a WebSocket, deployed. Then real messaging, the embeddable widget, presence, multi-tenancy, AI replies, canned responses, pre-chat, end-chat, email transcripts, and post-chat ratings. The rule was “boring and finished beats clever and abandoned” — shipping each phase before starting the next kept the momentum honest.
What I'd build next
A few things I deliberately left on the roadmap: a feedback / CSAT dashboard over the rating data; an operator history view to reopen and review ended chats; and richer branding — a logo in the widget and in the email transcripts. Further out sit the ideas that would turn it from a portfolio piece into a product: no-code chatbot flows, a multi-channel inbox (email, WhatsApp, Instagram), knowledge-base / RAG grounding for the AI, proactive triggered messages, analytics, and horizontal scaling across many Daphne processes — which Redis already makes correct.
Try the live demo, or read the full write-up on the project page.