Accounts · Public/Private Groups · Direct Messages · Real-time Messaging · File Uploads · Admin Dashboard
中文 · English · 日本語 · Online Demo · Project Documentation · Telegram Community
This might be the best Cloudflare chat room for teams under 10 million users
EdgeChat is a team chat system deployed on Cloudflare: accounts, public groups, private groups, direct messages, real-time messaging, file uploads, and an admin dashboard — everything you need. The goal is straightforward: run a production-ready, in-site IM in the Cloudflare ecosystem with as little operational overhead as possible.
- Interface Preview
- Online Demo
- Featured Feature: Telegram Two-Way Message Bridge
- Why EdgeChat
- Features
- Tech Stack
- Telegram Community
- Deployment
- Quick Start
- Project Structure
- Contributing
- Star History
- License
| Chat Interface | Admin Dashboard |
![]() |
![]() |
edgechat-demo.wcjxxgaq.workers.dev
The demo site reuses the production project's Vue pages, routing, state management, and real-time messaging logic, but all APIs, WebSocket, file uploads, and Telegram round trips are simulated in browser memory. Reload the page or click “Reset demo data” in the top-right corner to restore the initial state. It never contacts the production Worker, nor does it write to D1, KV, or R2.
Admins can bind any group in EdgeChat to a Telegram group. Once bound, messages on both sides are forwarded in real time, in both directions through the Telegram Bot — messages sent by EdgeChat members appear in the Telegram group, and messages from the Telegram group appear in EdgeChat. Members on both sides chat as if they were in the same group, with no need to switch apps or create duplicate groups.
| EdgeChat | Self-hosted Rocket.Chat / Mattermost | Commercial SaaS IM | |
|---|---|---|---|
| Deployment cost | Runs within Cloudflare's free tier | Requires an always-on server / container | Per-seat subscription fees |
| Ops burden | No server management, serverless | You maintain the database and cache yourself | No ops, but no control |
| Data ownership | Fully in your own Cloudflare account | Fully self-hosted | Data lives with a third party |
| Getting started | One-click auto-deploy via GitHub Actions | Manual / Docker Compose | Just sign up |
This table is only a rough reference for choosing a solution. Whether it actually fits depends on your team size and needs — feel free to discuss and correct it in the Issues.
💬 Messaging & Conversations
- Public groups, private groups, and direct message conversations
- Two-way Telegram group bridge — one Bot connects members on both sides
- Real-time messaging, paginated history, and file messages
- File uploads and avatar management
- Scheduled hard deletion of expired messages
🔐 Privacy & Security
- Newly written messages and newly uploaded attachments are encrypted server-side with AES-256-GCM; historical data is not bulk-backfilled
- The admin dashboard offers no entry point for reading group or direct message contents
- Users are created by admins; self-registration is not available
🛠 Admin Dashboard
- Top-level navigation for dashboard, user management, registration invites, and site settings
- Compares the current deployment directly against the source repository from the browser to check for updates
🎨 Experience
- Modern Liquid Glass-style interface
- Mobile-adapted, with basic accessibility support
Join our Telegram community to discuss with other users and developers, share feedback, and stay up to date with the project.
GitHub Actions deployment is recommended first — it suits long-term maintenance and production updates. The repository ships .github/workflows/deploy-worker.yml: pushing to master or main, or manually triggering workflow_dispatch, runs the automatic deployment.
- Quick start: https://echat.azora.top/guide/getting-started.html
- Detailed guide: https://echat.azora.top/guide/actions-deploy.html
🔐 Privacy & Server-Side Encryption (click to expand)
GitHub Actions manages the server-side encryption Worker Secrets. On the first deployment, if the target Worker has no encryption Secret, the workflow automatically generates a random 32-byte AES key, injects it as an independent versioned Secret, and records the current active key ID. Subsequent normal deployments only check that these Secrets exist — they never regenerate, overwrite, or rotate them. An existing production EDGECHAT_ENCRYPTION_KEYRING JSON keyring is preserved as-is and remains compatible.
After deployment, newly written message bodies and newly uploaded attachments are encrypted automatically. Historical D1 messages and R2 attachments stay untouched, and reads remain compatible with both legacy plaintext and new ciphertext. The project never loops through all historical data via Cron, scheduled tasks, or deployment scripts to encrypt it.
To provide a key manually, create a GitHub Repository Secret named EDGECHAT_ENCRYPTION_KEYRING in the following format:
{"activeKeyId":"v1","keys":{"v1":"BASE64_ENCODED_32_BYTE_KEY"}}The first deployment uses this value directly. To rotate an existing Worker automatically and incrementally, manually run Deploy Worker and tick rotate_encryption_key: the workflow only adds one versioned key Secret and switches the active key ID to the new version, while every old Secret and the legacy JSON keyring stay unchanged. New messages use the new active key, and old ciphertext keeps being decrypted with the key ID in its own envelope.
apply_encryption_keyring is a backup manual override. When using it, the Repository Secret must contain the complete JSON keyring: keys must keep every old key ID still referenced by historical ciphertext, then add the new key and update activeKeyId. Removing an old key makes the corresponding historical ciphertext permanently unreadable. apply_encryption_keyring and rotate_encryption_key cannot be enabled in the same run.
This is server-side encryption at rest, not end-to-end encryption. The Worker decrypts content only after session permission checks, so the Cloudflare Worker runtime and the deployer who holds the key remain inside the trust boundary. As a complementary privacy change, the admin message search and full-conversation viewing pages and their APIs have been removed; admins can still see aggregate statistics such as message counts.
Click to expand manual deployment and Docker notes
If you prefer to deploy manually, see the documentation site for the full steps, resource preparation, and notes:
- Manual deployment guide: https://echat.azora.top/guide/getting-started.html
- Documentation home: https://echat.azora.top/
- Docker local deployment: DOCKER.md
# Install dependencies
npm install
# Frontend development
npm run dev:frontend
# Frontend-only demo (separate port and build directory)
npm run dev:demo
# Local build
npm run build
# Local manual deployment
npm run deployMore scripts (demo build / deploy, CI environment variables)
# Build the standalone demo
npm run build:demo
# Deploy the standalone demo Worker
npm run deploy:demoThe demo uses wrangler.demo.toml and .github/workflows/deploy-demo.yml, with the Worker named edgechat-demo. Its GitHub Actions workflow is manual-trigger only and reads DEMO_CLOUDFLARE_ACCOUNT_ID and DEMO_CLOUDFLARE_API_TOKEN; it does not touch the existing production deployment workflow.
In non-interactive environments, set CLOUDFLARE_API_TOKEN before deploying.
The admin update check records the current GitHub repository, branch, and commit at build time. For accurate results, manual deployments should be built inside the Git repository from a clean commit that has already been pushed; the source repository must stay public so the browser can call the GitHub Compare API directly. The whole process creates no scheduled tasks.
PowerShell example:
$env:CLOUDFLARE_API_TOKEN = "your-token"
npm run deployClick to expand the directory tree
edgechat/
├─ assets/
│ └─ previews/
│ ├─ chat-home.png
│ └─ admin-dashboard.png
├─ frontend/
│ ├─ src/
│ │ ├─ api.js
│ │ ├─ router.js
│ │ ├─ store.js
│ │ ├─ ws.js
│ │ ├─ runtime.js
│ │ ├─ demo/
│ │ ├─ styles.css
│ │ ├─ components/ui/
│ │ └─ pages/
│ ├─ vite.config.js
│ └─ vite.demo.config.js
├─ worker/
│ ├─ schema.sql
│ ├─ migrations/
│ └─ src/
│ ├─ index.js
│ ├─ auth.js
│ ├─ db.js
│ ├─ middleware.js
│ ├─ utils.js
│ ├─ api/
│ └─ do/
├─ wrangler.toml
├─ wrangler.demo.toml
├─ package.json
├─ README.md
├─ README.en.md
├─ README.ja.md
└─ LICENSE
For more implementation details, see TECHNICAL.md and the documentation site: https://echat.azora.top/
Issues and pull requests are welcome — let's improve EdgeChat together.
Thanks to everyone who has helped the project:
Give us a star!
This project is licensed under GNU GPL v3.0 or later.
You may use, modify, and distribute this project. If you distribute a modified version, you must continue to provide the corresponding source code and keep it GPL-compatible.
Thanks to linux do for helping promote this project.


