A lightweight, real-time support chat widget for Django powered by SSE
Project description
๐ฌ django-supchat
A Lightweight, Real-Time Support Chat for Django
Zero dependencies. No WebSockets. No Redis. No React.
Just Django, vanilla JS, and Server-Sent Events.
Installation โข Demo โข Documentation โข Examples
โจ Overview
django-supchat is a production-ready, drop-in support chat widget for Django projects. It provides a beautiful, real-time chat experience between website visitors (guests or authenticated users) and your support team โ all powered by Django's ORM and Server-Sent Events (SSE).
๐ฏ Philosophy: Ship a powerful chat system without the complexity of WebSockets, Redis, or a frontend build step. Just
pip installand go.
๐ Key Features
๐ฆ Quick Start
Get up and running in under 2 minutes.
1. Install
pip install django-supchat
2. Configure Django
# settings.py
INSTALLED_APPS = [
# ...
"supchat",
]
# Optional: Customize the widget
SUPCHAT = {
"TITLE": "Support",
"POSITION": "right", # "right" or "left"
"THEME": "auto", # "auto", "light", or "dark"
"ALLOW_GUEST": True,
"MAX_MESSAGE_LENGTH": 2000,
}
3. Add URLs
# urls.py
from django.urls import include, path
urlpatterns = [
# ...
path("supchat/", include("supchat.urls")),
]
4. Run Migrations
python manage.py migrate
5. Render the Widget
{% raw %}
{% load supchat %}
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Site</title>
</head>
<body>
<h1>Welcome to my site!</h1>
{% supchat %}
</body>
</html>
{% endraw %}
That's it! ๐ Your chat widget is live.
๐ Documentation
Configuration Reference
Widget Settings
| Setting | Type | Default | Description |
|---|---|---|---|
TITLE |
str |
"Support" |
Widget title displayed in header |
POSITION |
str |
"right" |
Widget position: "right" or "left" |
THEME |
str |
"auto" |
Theme: "auto", "light", or "dark" |
ALLOW_GUEST |
bool |
True |
Allow anonymous visitors to chat |
MAX_MESSAGE_LENGTH |
int |
2000 |
Maximum characters per message |
Advanced Settings
| Setting | Type | Default | Description |
|---|---|---|---|
HEARTBEAT_INTERVAL |
int |
25 |
SSE heartbeat interval (seconds) |
SSE_RETRY_MS |
int |
5000 |
SSE reconnection delay (ms) |
GUEST_COOKIE_NAME |
str |
"supchat_guest" |
Name of the guest identity cookie |
GUEST_COOKIE_AGE |
int |
31536000 |
Cookie lifetime (1 year in seconds) |
RATE_LIMIT |
dict |
{"MESSAGES": 30, "WINDOW": 60} |
Default rate limit config |
RATE_LIMIT_CALLBACK |
callable |
None |
Custom rate limit function |
Per-Render Overrides
You can override settings per template render:
{% raw %}
{% supchat title="Help Desk" position="left" theme="dark" %}
{% endraw %}
๐ Security Model
django-supchat takes security seriously:
- โ CSRF Protection โ All POST endpoints require valid CSRF tokens
- โ Signed Guest Cookies โ Guest identity stored in signed, HTTP-only cookies
- โ Conversation Access Control โ Every endpoint (including SSE) verifies access
- โ Input Sanitization โ HTML stripped, control chars removed, length capped
- โ
XSS Prevention โ Frontend uses
textContent, neverinnerHTML - โ Rate Limiting โ Cache-backed default + pluggable hook for custom logic
Custom Rate Limiting
# settings.py
def my_rate_limiter(request, action):
# Return True to allow, False to deny
if request.user.is_staff:
return True
return False # Custom logic
SUPCHAT = {
"RATE_LIMIT_CALLBACK": my_rate_limiter,
}
๐ฅ Operator Management
Creating Operators
Create Operator records in Django admin for your support staff:
from django.contrib.auth import get_user_model
from supchat.models import Operator
User = get_user_model()
user = User.objects.get(username="support_agent")
Operator.objects.create(user=user, is_online=True)
Assigning Operators Programmatically
from supchat.services import assign_operator
# Auto-assign to current user (if they're an operator)
assign_operator(request, conversation)
# Assign to a specific operator
assign_operator(request, conversation, operator=some_operator)
Operator Dashboard
Access the operator panel at /supchat/operator/ (requires staff permissions).
Features:
- ๐ฌ Real-time conversation list with unread badges
- ๐ Analytics dashboard with 7-day & 30-day charts
- ๐ฏ Conversation assignment & status management
- ๐ Dark/Light theme toggle
- ๐ Bilingual interface (EN/FA)
๐ ๏ธ Public API
The service layer is the stable integration point. Use these functions in your views, signals, or management commands:
from supchat.services import (
get_or_create_conversation,
send_message,
close_conversation,
assign_operator,
mark_messages_read,
)
get_or_create_conversation(request) โ (Conversation, guest_id | None)
Returns an open conversation for the user/guest. Creates one if none exists.
conversation, guest_id = get_or_create_conversation(request)
send_message(request, conversation, text) โ Message
Sends a message and broadcasts it via SSE.
message = send_message(request, conversation, "Hello!")
close_conversation(request, conversation) โ Conversation
Closes a conversation (operators only).
close_conversation(request, conversation)
assign_operator(request, conversation, operator=None) โ Conversation
Assigns an operator to a conversation.
assign_operator(request, conversation, operator=my_operator)
mark_messages_read(request, conversation, message_ids=None) โ int
Marks messages as read. Returns count of updated messages.
count = mark_messages_read(request, conversation)
๐จ Customization
Override any of these in your project:
your_project/
โโโ templates/
โ โโโ supchat/
โ โโโ widget.html # Override the widget template
โโโ static/
โโโ supchat/
โโโ supchat.css # Override styles
โโโ supchat.js # Override behavior
CSS Variables
Customize colors by overriding CSS variables:
.supchat-widget {
--sc-primary: #6366f1;
--sc-primary-hover: #4f46e5;
--sc-bubble-user: linear-gradient(135deg, #6366f1, #8b5cf6);
--sc-bubble-agent: #ffffff;
--sc-bg: rgba(255, 255, 255, 0.95);
--sc-fg: #0f172a;
--sc-border: rgba(226, 232, 240, 0.8);
}
JavaScript Events
Listen to chat events:
document.addEventListener('supchat:open', () => {
console.log('Chat opened');
});
document.addEventListener('supchat:close', () => {
console.log('Chat closed');
});
document.addEventListener('supchat:message', (e) => {
console.log('New message:', e.detail);
});
๐ข Deployment
SSE Requirements
The built-in SSE manager is process-local and works great for:
- Development
- Single-process deployments
- Small to medium traffic
For multi-worker deployments (Gunicorn, uWSGI with multiple workers), clients connected to different workers won't receive broadcasts. Solutions:
Option 1: Single Worker
gunicorn myproject.wsgi:application --workers 1 --threads 8
Option 2: Cross-Worker Fanout
Implement your own broadcast mechanism using Redis Pub/Sub, a message queue, or your cache backend:
# myproject/sse_bridge.py
from django.core.cache import cache
from supchat.sse import sse_manager
def broadcast_to_all_workers(conversation_id, event, data):
# Publish to Redis/cache
cache.set(f"supchat:broadcast:{conversation_id}", {
"event": event,
"data": data,
}, timeout=5)
# Each worker subscribes and calls:
# sse_manager.broadcast(conversation_id, event, data)
Proxy Configuration
Nginx:
location /supchat/ {
proxy_pass http://localhost:8000;
proxy_buffering off; # Critical for SSE
proxy_cache off;
proxy_read_timeout 86400s; # Long timeout for SSE
proxy_send_timeout 86400s;
}
Apache:
<Location /supchat/>
ProxyPass http://localhost:8000/supchat/
ProxyPassReverse http://localhost:8000/supchat/
SetEnv proxy-nokeepalive 1
SetEnv proxy-sendchunked 1
</Location>
๐ Browser Support
| Browser | Version |
|---|---|
| Chrome | 90+ |
| Firefox | 88+ |
| Safari | 14+ |
| Edge | 90+ |
| iOS Safari | 14+ |
| Android Chrome | 90+ |
๐บ๏ธ Roadmap
- File/image attachments
- Message reactions & emoji
- Conversation tags & categories
- Canned responses / quick replies
- Chat transcripts via email
- Webhook integrations (Slack, Discord)
- Bot/AI auto-responses
- Multi-language support (beyond EN/FA)
- Mobile SDK (iOS/Android)
- WebSocket adapter (optional)
๐ค Contributing
Contributions are welcome! Here's how:
- Fork the repo
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
Development Setup
git clone https://github.com/xo-aria/django-supchat.git
cd django-supchat
pip install -e '.[test]'
pytest
๐ License & Trademark
Code License
django-supchat is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).
This means:
- โ You can use, modify, and distribute this software
- โ You can use it commercially
- โ ๏ธ You must disclose source code (even for SaaS/network services)
- โ ๏ธ You must include the same license in distributions
- โ ๏ธ You must state changes you made
๐ Read the full AGPL-3.0 license
Trademark Policy
The name "SupChat" is a trademark of xo-aria. See the Trademark Policy for details on:
- โ How to use the SupChat name
- โ Attribution requirements
- โ What you cannot do
- ๐จ Logo usage guidelines
Quick Summary:
- You must keep "SupChat" in the name when distributing
- You must include attribution:
Based on SupChat by xo-aria - https://github.com/xo-aria/django-supchat - You cannot rebrand without mentioning SupChat
- You cannot use SupChat logos without permission
Why AGPL-3.0?
We chose AGPL-3.0 to:
- Protect user freedom - Ensure the software stays free
- Close the SaaS loophole - Even network services must share source code
- Encourage contributions - Improvements benefit everyone
- Maintain quality - Prevent closed-source forks from fragmenting the project
Commercial Use
Yes, you can use SupChat commercially! Just:
- โ Comply with AGPL-3.0 (disclose source code)
- โ Follow the trademark policy (attribution)
- โ Document your changes
Need a commercial license without AGPL restrictions? Contact us.
๐ Attribution
If you use SupChat in your project, we'd appreciate:
Required (by license):
Based on SupChat by xo-aria
https://github.com/xo-aria/django-supchat
Licensed under AGPL-3.0
Appreciated (but optional):
- โญ Star the repository on GitHub
- ๐ Mention "Powered by SupChat" in your docs/about page
- ๐ Link back to https://github.com/xo-aria/django-supchat
- ๐ฆ Tweet about it (we'd love to see your projects!)
๐ Support & Contact
Bug Reports & Feature Requests:
- ๐ GitHub Issues
Questions & Discussions:
- ๐ฌ GitHub Discussions
Commercial Licensing:
- ๐ง Email: [your-email@example.com]
- ๐ผ Custom licensing available for closed-source projects
Security Issues:
- ๐ Please email security issues directly to [your-email@example.com]
- โ ๏ธ Do not open public issues for security vulnerabilities
If django-supchat helps your project, please consider:
โญ Starring on GitHub โข ๐ด Forking โข ๐ฌ Joining Discussions
Made with โค๏ธ by xo-aria
๐ Acknowledgments
- Built with โค๏ธ for the Django community
- Inspired by Intercom, Crisp, and Tawk.to
- Icons from Lucide
- Charts powered by Chart.js
๐ Support
- ๐ Bug Reports: GitHub Issues
- ๐ก Feature Requests: GitHub Discussions
- ๐ง Email: your-email@example.com
If django-supchat helps your project, consider giving it a โญ on GitHub!
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_supchat-1.0.0.tar.gz.
File metadata
- Download URL: django_supchat-1.0.0.tar.gz
- Upload date:
- Size: 54.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
08072a0f9c2ac65bc4013d90a62fedbdf29320037d0854e5947ef9a3d710ba41
|
|
| MD5 |
18036d2d4443d1a8bda340ddd8298bd9
|
|
| BLAKE2b-256 |
457491f0e077747bd000c78e5bb28947d49730e49a1a098f2d6386cd8a84c38f
|
File details
Details for the file django_supchat-1.0.0-py3-none-any.whl.
File metadata
- Download URL: django_supchat-1.0.0-py3-none-any.whl
- Upload date:
- Size: 56.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7736c0ba3ee4843c52b5db1169aa538053ac81eb204ccefb363786fd1d4e27c8
|
|
| MD5 |
1fc037304cc918883f7881eab846fc25
|
|
| BLAKE2b-256 |
06cfb9df296334f610bff63eecb00e3acd2539a58103b3e400c78754edec67b1
|