Skip to content

Repository files navigation

Webtel

A chat widget for your website. Reply to visitors from Telegram or a small web inbox.

This is the single-owner, self-hosted version. One deployment connects to your bot and support chat. No signup service or multi-customer platform.

Text, images, video, audio and documents are supported, with separate visitor conversations and Open / Pending / Resolved statuses. Runs on Cloudflare Workers + D1. Plain HTML, CSS and JavaScript on the frontend.

Run locally

Use Node 24 and npm.

git clone https://github.com/oladapodev/webtel.git
cd webtel
npm ci
cp .dev.vars.example .dev.vars

Set ADMIN_TOKEN in .dev.vars to a random secret of at least 32 characters. You can generate one with openssl rand -hex 32. Keep this file private.

npm run db:local
npm run dev

Open http://localhost:8799 and sign in with that token. The dashboard works locally without Telegram. The widget appears when you use the installation preview.

Connect Telegram and deploy

  1. Create a dedicated bot with @BotFather, then open your bot and press Start.
  2. Fill in .dev.vars: TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID, and a random TELEGRAM_WEBHOOK_SECRET (openssl rand -hex 32). For a private chat, your Telegram user ID is the chat ID. You can find it with @userinfobot. Set TELEGRAM_AGENT_IDS to the Telegram user IDs allowed to reply, separated by commas.
  3. Create your own database:
npx wrangler login
npx wrangler d1 create webtel

Replace the placeholder database_id in wrangler.jsonc with the returned ID. Choose a Worker name that is not already used by another app in your account. In vars.SITES, add your website's exact origin and your Worker URL. For example, https://example.com, without a path. www.example.com is a different origin.

npm run db:remote
npx wrangler secret put ADMIN_TOKEN
npx wrangler secret put TELEGRAM_BOT_TOKEN
npx wrangler secret put TELEGRAM_CHAT_ID
npx wrangler secret put TELEGRAM_WEBHOOK_SECRET
npx wrangler secret put TELEGRAM_AGENT_IDS
npm run deploy
WEBTEL_URL=https://YOUR_WORKER.workers.dev npm run telegram:setup

Enter the same values from .dev.vars when Wrangler prompts. Telegram needs a public HTTPS webhook, so local development alone will not receive replies. Don't connect a bot that another application is using.

Add this before </body> on your website, using your deployed URL:

<script src="https://YOUR_WORKER.workers.dev/widget.js" data-site="default" defer></script>

Send a test message. In Telegram, tap Connect, wait for confirmation, then reply normally. Switch changes the active conversation. Disconnect stops routing your messages. Replying to a specific bot message still works.

Give this to your AI agent

Copy the block below into your coding agent. It can set up a standalone deployment or adapt the widget to your app.

Set up https://github.com/oladapodev/webtel for my website.

Read the README, wrangler.jsonc, src/index.ts, public/widget.js and
scripts/telegram-setup.mjs first. This is the single-owner version, not
a hosted signup platform. Keep the implementation simple.

1. Clone the repo if needed. Run npm ci, npm run check and npm test.
2. Inspect my app before changing it. Ask for my website origin and whether
   I want a separate Worker or integration into my existing Cloudflare app.
3. Create .dev.vars from the example only if it does not already exist.
   Generate strong admin/webhook secrets. Let me supply my bot token,
   support chat ID and allowed Telegram user IDs securely. Never put
   secrets in source code, the widget snippet, Git, or your final reply.
4. Run npm run db:local and npm run dev. Open the dashboard and check it.
5. With my approval, create a new D1 database, set its ID and allowed origins,
   upload secrets, apply remote migrations, and deploy. Do not overwrite
   an existing Worker/database or replace another app's bot webhook.
6. Register the webhook with WEBTEL_URL=<deployed URL> npm run telegram:setup.
   Add the widget script to my site's HTML, or load it once from the app's
   root layout if it is an SPA. Use my own Worker URL, not someone else's.
7. Test the real flow: website message -> Telegram Connect -> normal reply
   -> website. Check two independent visitors don't receive each other's
   replies, try an image in both directions, and check status changes.
8. If adapting the backend, preserve session-token authentication, exact
   origin checks, agent restrictions, deduplication and protected media
   downloads. Run the tests again. Tell me what you verified and what is
   blocked by missing credentials or access. Don't claim an untested deploy.

A few limits

  • The widget polls every 3 seconds. It does not use WebSockets.
  • Files are limited to 10 MiB and stored by Telegram. Downloads go through authenticated Worker endpoints. Telegram may recompress photos or treat some media as documents.
  • Outbound text delivery retries, so duplicates are possible after an uncertain network failure.
  • Conversations are stored in D1, files in Telegram, and visitor session credentials in browser local storage. There is no automatic chat deletion. Set a retention policy for your site.
  • Cloudflare and Telegram quotas still apply. Free-tier availability is not a promise of unlimited free hosting.

npm run check checks TypeScript. npm test runs Worker/D1 integration tests with Telegram mocked. Real bot delivery still needs the end-to-end check above.

MIT licensed.

About

Self-hosted website support chat with Telegram replies. Cloudflare Workers + D1.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages