A bilingual admin panel for Telegram bots, shops, VPN/service businesses and a customer Mini App — running on Cloudflare Workers
This page is in English. Use the button above for the Persian version.
How to read this page: every section is an accordion. Click the ▸ arrow next to a heading to expand its full explanation, and click again to collapse it. Each panel section is documented separately, from zero to one hundred.
| # | Section | Topic |
|---|---|---|
| 1 | At a glance | What the bot does |
| 2 | Requirements | What you need first |
| 3 | Zero-to-one-hundred setup | From BotFather to deployment |
| 4 | First login and hardening | Private password and sessions |
| 5 | Connecting the bot | Token, webhook, username |
| 6 | Panel sections, one by one | Every screen explained |
| 7 | Customer Mini App | The shop inside Telegram |
| 8 | The bot as your users see it | Commands and button behaviour |
| 9 | Backups, reports and security | Maintenance |
| 10 | Development and testing | For contributors |
| 11 | Screenshot gallery | Every screen |
| 12 | Troubleshooting | Common errors |
| 13 | Creator and contact | aMirsEdighian |
▸ What is this project and what does it do?
BotPanel is a complete admin panel for Telegram bots that runs on Cloudflare Workers — no rented server, no Docker, no separate database and no static IP. The whole system boots inside one Worker backed by a Durable Object (SQLite).
A single installation gives you:
- Bot management: menus, inline buttons, sub-menus, start and help texts, fully bilingual (Persian/English).
- Users: list, search, block, tags and statistics.
- Broadcasting: text, photo, polls, delivery to users or channels, a queued sender and delivery reports.
- Shop: products, orders, bank-transfer receipts, discount codes, automatic file delivery.
- Service / VPN: Marzban / Marzneshin and other providers, plans, ready-made config stock, renewals, wallets, resellers.
- Customer Mini App: shop and account area inside Telegram, including a live support chat.
- Support desk: customer tickets inside the panel; an admin reply lands in the Mini App and in the customer's Telegram chat.
- Loyalty: points, spin wheel, raffles, dice and gifts.
- Groups: rules, anti-link, forward stripping, welcome messages and member moderation.
- Multi-bot: run several independent bots from one panel.
▸ Technical architecture in one table
| Layer | Technology | Note |
|---|---|---|
| Runtime | Cloudflare Workers | Serverless, runs at the edge |
| Routing | Hono | Everything under /api |
| Storage | Durable Object with SQLite | Class BotCoordinator |
| Migration source | KV (BOT_KV) |
Read-only, for legacy data |
| UI | Plain HTML/CSS/JS + Tailwind (built locally) | No external CDN at runtime |
| Scheduling | Cron every minute | Queued broadcasts, renewals, reminders |
| Mini App | Telegram WebApp | Served from /portal |
Key files: src/index.js (routes), src/telegram.js (bot logic), src/services/ (service/VPN module), public/ (panel and Mini App).
▸ What's new in v3.4
- Nation-wide news publisher (Iran + world): one 📰 button after
/start, then a choice between Iran news and world news; each opens its own categories (breaking, politics, economy, sports, tech). World headlines are automatically translated to Persian (30-day cache). Schedule delivery to channels/groups by a fixed daily time (Tehran) or a repeating interval. - Clean custom/default bots: a bot whose purpose is Default/Custom starts with no buttons at all until the admin adds buttons in Menus & Buttons; no system default buttons are shown, and an explicitly saved empty button list stays empty.
- One-button rates bot: the rates purpose opens with a single 📈 USD, gold & Tether button, then the asset categories; live table with 24h change, send-now, and a daily scheduled publish (asset type + Tehran time + destinations).
- Full
/admininside Telegram: every control that exists in the web panel is available to the admin as glass buttons — stats, news, rates, menus & buttons, shop, broadcast, media, locks, webhook, tuning, services, tokens and more. Tapping a button edits the same message in place and reveals the next options; no new messages are stacked. - Password on every panel entry: the panel session no longer persists in localStorage; the password is required on every new tab/window or browser restart (Telegram mini-app login is unaffected).
- Regenerable screenshots: run
npm run screenshotsto capture every README image from a fresh local build.
▸ What you need before you start
| Item | Why | Required? |
|---|---|---|
| Node.js 22.16+ | Building and running locally | Yes |
| Cloudflare account | Workers and Durable Objects | Yes |
| Bot token | From @BotFather | Yes |
| Git | To clone the source | Yes |
| A media channel/group | For direct file uploads | Optional |
| Payment gateway | ZarinPal, Telegram Stars, crypto | Optional |
| VPN provider panel | Marzban / Marzneshin, etc. | Service mode only |
Check your Node version:
node -v # must be 22.16.0 or newer▸ Step 1 — Create the bot in BotFather
- Open @BotFather in Telegram and send
/newbot. - Pick a display name, then a username ending in
bot. - You receive a token such as
123456789:AAE.... Store it safely and never commit it to Git. - Optional but useful:
/setdescriptionand/setabouttextto introduce the bot./setuserpicfor the avatar./setprivacy→ Disable it if the bot must read all group messages./setmenubutton→ you can point this at the Mini App later.
▸ Step 2 — Clone the source and install dependencies
git clone https://github.com/developerAmira/telegram-bot-panel.git
cd telegram-bot-panel-v2
npm cinpm ci installs the exact versions locked in package-lock.json, so your build matches the tested one.
Then build the static UI assets:
npm run buildThis produces CSS, fonts and icons locally inside public/, so the panel never depends on an external CDN at runtime.
▸ Step 3 — Log in to Cloudflare and review wrangler.toml
npx wrangler loginOpen wrangler.toml. These blocks are mandatory:
name = "telegram-bot-panel-v2"
main = "src/index.js"
[[durable_objects.bindings]]
name = "BOT_STATE"
class_name = "BotCoordinator"
[[migrations]]
tag = "v2-durable-state"
new_sqlite_classes = ["BotCoordinator"]
[triggers]
crons = ["* * * * *"]nameis your Worker name. If you already run another deployment, choose a different name so it is not replaced.BOT_STATEis the primary data store; Cloudflare provisions it during deployment.cronspowers queued broadcasts, service renewals and reminders.- Leave the
ASSETSandrun_worker_firstrules for/api/*,/telegram/*,/pay/*and/internal/*untouched.
KV: the BOT_KV binding is only read, to import data from older versions. For a brand-new installation create an empty namespace:
npx wrangler kv namespace create BOT_KVand put the resulting id in wrangler.toml.
▸ Step 4 — Configure secrets
npx wrangler secret put WEBHOOK_SECRET
npx wrangler secret put BOT_TOKEN| Name | Purpose | Notes |
|---|---|---|
WEBHOOK_SECRET |
Signs incoming Telegram requests | Random 32-char string of letters, digits, _, - — required |
BOT_TOKEN |
Bot token | Can also be saved from inside the panel, which takes precedence |
VAULT_KEY |
Encrypts VPN provider and gateway credentials | Required for the service module (32 characters) |
ADMIN_PASSWORD |
Fallback login password | Optional; a password stored in the panel wins |
BACKUP_PASSWORD |
Encrypts backup archives | Optional |
Generate a safe random value:
node -e "console.log(require('crypto').randomBytes(24).toString('base64url'))"
⚠️ Never place these values in source code,wrangler.tomlor a commit.
▸ Step 5 — Run locally before publishing
npm run devThe panel starts on http://127.0.0.1:8787. Locally you can review the layout, menus and settings. Real Telegram traffic needs a public URL, so full bot testing happens after deployment.
Run the automated tests:
npm test▸ Step 6 — Deploy to Cloudflare
npm run deployTo inspect the output without publishing:
npm run build
npx wrangler deploy --dry-runYou end up with a URL such as https://telegram-bot-panel-v2.<subdomain>.workers.dev. That single URL is both the admin panel and the webhook target.
If you use Cloudflare's Git integration, make sure it follows this repository and the main branch, and that the secrets exist in that environment.
▸ Signing in with the default password and creating a private one
- Open the Worker URL in a browser.
- On a fresh installation the initial password is
botpanel123— no environment variable required. - Immediately after login the panel shows the create a private password form. A default-password session can reach nothing else until the password is changed.
- Save the new password. All previous sessions are invalidated and only the new password works.
🔒 The default password is public knowledge, so complete this step right after your first deployment. For extra safety you can put the first release behind Cloudflare Access.
Later password changes happen in Settings → Security.
🔐 Password on every entry (v3.4): the panel session lives in the tab's temporary storage (sessionStorage), not in the browser's persistent storage. Opening the panel in a new tab or window — or restarting the browser — always asks for the password again. Admin login inside Telegram still works without a password via
initDataverification.
▸ Saving the token, testing the connection, registering the webhook
- Go to Settings → Bot settings and paste the BotFather token.
- Choose the bot language: Persian only, English only, or bilingual (the user picks).
- In Settings → Webhook management, press Set webhook. This registers the Worker URL, the
WEBHOOK_SECRETand every update type the panel needs, includingchat_memberandchannel_post. - The webhook status box shows the current state; if it reports a last error, verify the URL and the secret.
- Send
/startto the bot from a test account. A reply means everything is wired up.
⚠️ A Telegram token can only have one active webhook. Registering it here stops any other service that used the same token.
Groups: make the bot an administrator with delete-message and restrict permissions. If it must see every group message, disable Privacy Mode in BotFather.
Every subsection below is documented separately and completely. Click the ▸ arrow.
▸ Dashboard — the pulse of your bot
What you see:
- Total users, users active today, new users.
- Bot health: token, webhook and username status.
- Recent broadcasts and their delivery rate.
- Unread support tickets.
- Sales/service summaries when those modules are enabled.
How to use it:
- You land here automatically after logging in.
- The cards are clickable and take you to the matching section.
- A zero simply means the related module has not been enabled or used yet.
Note: all numbers come from live SQLite data; no manual refresh loop is needed.
▸ Overview and choosing the bot purpose
The Studio is where the bot is built. Your first decision is the bot purpose:
| Purpose | Best for |
|---|---|
| Shop | Selling digital or physical products |
| Service / VPN | Selling and renewing configs or accounts |
| Channel owner | Scheduled publishing and member management |
| Group moderation | Rules, anti-link, welcome messages |
| FAQ | A question-and-answer bot |
| Education | Courses with progress tracking |
| Custom | Tick the exact modules you want |
How to use it:
- Open Bot Studio → Overview.
- Click the card you want; the selected card gets a coloured border.
- Press Save. The tab bar now shows only the relevant tabs.
- In Custom mode a module checklist appears — enable exactly what you need.
Important: changing the purpose never deletes data; it only changes which tabs are visible.
▸ Catalog (products)
Purpose: define digital or physical products for sale inside the bot.
Step by step:
- Bot Studio → Catalog → Add product.
- Fill in title, description, price and image.
- For a free product set the price to
0; the button becomes “Get” instead of “Buy”. - In Delivery, define the file or text the customer receives after payment.
- Use the product deep link to sell straight from a channel post.
Note: if a channel lock is active, the customer must join first; the purchase then resumes automatically.
▸ Orders and receipts
Purpose: track purchases and approve bank-transfer payments.
Step by step:
- Bot Studio → Orders lists every order with its state: pending, receipt review, paid, rejected.
- For bank transfers, the customer's receipt photo is shown inline.
- Approve delivers the product instantly and marks the order paid.
- Reject asks for a reason, which is forwarded to the customer.
Note: if the buyer leaves a required channel after ordering, delivery is held until they rejoin.
▸ Discount codes
- Bot Studio → Discounts → New code.
- Set the code (e.g.
WELCOME20), the type (percentage or fixed amount), a usage cap and an expiry date. - Optionally restrict the code to a single product or plan.
- The customer enters the code at checkout and the price updates immediately.
▸ Scheduled channel publishing
- Make the bot an administrator of the channel.
- Open Bot Studio → Publishing and enter the channel id.
- Compose the post, attach media and buttons, and pick a publish time.
- The one-minute cron checks the queue and posts on schedule.
- The publish history with success/failure state lives in the same tab.
▸ Group moderation
- Add the bot to the group as an administrator with delete and restrict rights.
- The group appears under Bot Studio → Groups but stays off until you enable it manually.
- Per group you can enable: welcome messages, anti-link, anti-spam, removal of other channels' posts, word filters and a night lock.
- Violations are counted; once the threshold is crossed the bot warns or mutes.
▸ Relay (forward stripping)
This tool republishes a source channel's posts in a destination without the “forwarded from” label.
- Make the bot an admin in both the source and destination channels.
- Define the pair in the Relay tab.
- Optionally add replacement text, a signature or custom buttons.
▸ Loyalty club (points and rewards)
- Open the Loyalty tab and set the points for each event: joining, purchasing, inviting a friend, daily activity.
- Define tiers (bronze, silver, gold …) and the reward per tier.
- Customers see their points and tier in the bot and in the Mini App.
- Prize mechanics such as the spin wheel and raffles are configured in Service → Rewards.
▸ FAQ
- FAQ tab → Add question.
- Write the question and answer (for both languages if the bot is bilingual).
- Control the display order.
- In the bot the user sees the question list, and selecting one edits the same message to show the answer instead of sending a new message.
▸ Media and direct uploads
- First configure one of these in Settings → Files and media:
- the numeric id of an admin who has already started the bot, or
- a dedicated channel/group where the bot may post (and preferably delete).
- In the Media tab pick a file. It is sent to that chat, the
file_idis stored and the temporary message is deleted. - The stored media can then be reused in products, channel posts and broadcasts.
Limits: 10 MiB for photos, 20 MiB for other files. Changing the bot token requires re-uploading media.
▸ Managing users
What you see: everyone who has started the bot, with name, id, language, join date and status.
What you can do:
| Task | How |
|---|---|
| Search | Type a name or numeric id in the search box |
| Block | The “Block” button on the row; the bot stops answering them |
| Unblock | The same button while blocked |
| Inspect | Click the row for orders, wallet, tickets and points |
| Direct message | Send a message straight from the detail view |
| Paginate | Next/previous buttons under the table |
Note: users cannot be deleted, because order history depends on them — block them instead.
▸ Messaging every user — step by step
The screen itself is built from accordions:
| Section | Purpose |
|---|---|
| Audience | All users, a custom id list, or a channel/group |
| Text | Text message with inline buttons |
| Poll | Build a poll with custom options |
| Photo | Photo with a caption |
| Results | Sent, failed and blocked counts |
| History | Previous broadcasts and their state |
Step by step:
- Open Audience and choose the destination.
- Open one of Text / Poll / Photo and compose the content.
- Add inline buttons with a label and URL if needed.
- Press Send. Delivery runs as a background queue, so you can close the page.
- Watch progress under Results; users who blocked the bot are flagged automatically.
Throughput: batch size and delay live in Settings → Broadcast tuning. The defaults are safe for Telegram's rate limits.
▸ Tickets, admin replies and the Mini App chat
What you see: the list of support conversations. Each customer has one continuous thread, with an unread counter next to their name.
Workflow:
- The customer writes from the bot's support button or from the Mini App support tab.
- The message is stored instantly in Panel → Support and the unread counter increases.
- Click the thread to read the full history; opening it marks the messages as read.
- Type your answer and press Send. The reply goes out simultaneously:
- as a Telegram message to the customer, and
- into their Mini App support tab.
- Close archives the thread; the customer's next message reopens it.
Related settings:
- To pin a support button under every bot message: Settings → Bot settings → Always show support button.
- To be notified of new messages in a staff group: set the report chat in Service → Settings.
▸ Building the menu, sub-menus and the start text
This screen is also accordion-based:
| Section | Purpose |
|---|---|
| Start text | The first message a user sees after /start |
| Help text | The answer to the help button/command |
| Page buttons | Inline buttons under the message |
| Sub-menus | Nested pages |
Step by step:
- Open Start text and write the welcome message (both languages in bilingual mode).
- Under Page buttons, press Add button to create rows. A button can:
- open a URL,
- open a sub-menu,
- show static text, or
- run a built-in action (shop, service, support, points …).
- Arrange buttons across rows; each row holds one to three buttons.
- Create sub-menus and point buttons at them; a back button is added automatically.
- Save and send
/startto the bot to see the result.
New behaviour in v3.1: pressing a button edits the existing message with the new text and buttons, so the chat never fills with duplicates. Delivered content (files, configs, receipts) is still sent as a new message so it stays in the history.
▸ Bot settings (token, language, support button)
- Bot token: paste the BotFather token. The value stored here overrides the environment variable.
- Bot language: bilingual, Persian only, or English only. In bilingual mode the user picks on first run.
- Default language: the language new users get until they change it.
- Always-on support button: pins a support button under every bot message; provide the label per language.
Every block on this screen is an accordion, with an expand/collapse all button at the top. Each block remembers whether you left it open.
▸ Security (password and sessions)
- Enter the current password.
- Type the new password twice.
- Press Change password; all other sessions are invalidated immediately.
If you lose the password, set the ADMIN_PASSWORD variable in Cloudflare and reset the stored record through it.
▸ Channel membership lock
- Tick Enable lock.
- Enter the channel id (
@channel) and a join link. - Make the bot an administrator of that channel so it can verify membership.
- Non-members see a join prompt with a Check membership button; once they join, their pending action (for example a product deep link) resumes automatically.
The lock can be scoped to a single area (shop, service, groups) instead of the whole bot.
▸ Webhook management
- Set webhook: registers the current Worker URL with the secret and required update types.
- Delete webhook: disconnects Telegram from this Worker (useful when moving the bot).
- The status box shows the last error and the pending update count — start troubleshooting here.
▸ Broadcast tuning
- Batch size: messages per round (1–50).
- Delay (ms): pause between batches (20–500).
If you hit rate-limit (429) errors, lower the batch size and raise the delay.
▸ Panel preferences (theme and language)
- Six built-in themes: dark, light, ocean, violet, forest, sunset.
- Panel language: Persian or English, independent of the bot language.
- Your choice is stored in the browser.
▸ Overview and enabling the service module
This module sells services (VPN, subscriptions, accounts) and has 13 tabs. To start:
- Make sure
VAULT_KEYis configured as a secret — without it provider credentials cannot be stored. - In Bot Studio → Overview set the purpose to Service / VPN, or enable the “services” module in Custom mode.
- Open Bot Studio → Service / VPN.
Performance: the workspace shell renders immediately while each tab's body loads behind it and is cached briefly, so switching tabs is instant. Any data change clears the cache automatically.
▸ Providers
- Press Add provider and pick the type: Marzban, Marzneshin, manual stock, and so on.
- Enter the URL, username and password. Credentials are encrypted with
VAULT_KEYand are never returned by the API. - Press Test connection; on success the provider version is displayed.
- Enable the provider so it can be selected in plans.
▸ Plans
- New plan → title, provider, duration (days), volume (GB), price.
- Choose the allowed roles: customer, reseller, credit reseller.
- Set the extra-GB and extra-day prices used for renewals.
- If the plan is fulfilled from stock, select the stock shelf.
- A saved plan is immediately purchasable in the bot and the Mini App.
▸ Stock
For selling ready-made configs:
- Create a shelf (e.g. “Germany 30 days”).
- Use bulk import to paste configs line by line.
- Inventory is shown live and one item is consumed per sale.
- Low stock raises a warning on the overview tab.
▸ Services (active subscriptions)
Every sold service with its owner, plan, expiry date and usage.
- Inspect: subscription link, traffic usage and status.
- Manual renewal: add days or volume without a payment.
- Suspend/resume: temporarily disable a service.
- Delete: only once it is also removed from the provider.
▸ Operations
Every purchase, renewal or change creates an “operation”. If the provider connection drops mid-flight the operation stays uncertain and the system reconciles it automatically so no duplicate service is created. From this tab you can inspect or retry unfinished operations.
▸ Wallets
- Each customer's balance plus deposit and spend history.
- Manual credit/debit with a mandatory reason (for support and compensation).
- Credit limits for credit resellers.
▸ Payments and gateways
Supported methods:
| Method | Notes |
|---|---|
| Bank transfer | The customer uploads a receipt, an admin approves it |
| ZarinPal | Online IRR payments |
| Telegram Stars | In-app Telegram payments |
| Crypto (TON/TRON — USDT) | Automatic transaction verification |
Enter each gateway's keys in this tab; sensitive values are stored encrypted. Transactions are listed with their state (pending, verified, failed).
▸ Requests
Requests that need a human decision: reseller upgrades, credit increases, config replacements and refunds. Each row has Approve and Reject, and the customer is notified instantly.
▸ Promotions
Service-specific discount codes, wallet gift codes and referral campaigns. Each code supports a usage cap, an expiry date and plan restrictions.
▸ Rewards (wheel, raffle, dice)
- Spin wheel: define prizes and odds, plus a daily budget and a cooldown between spins.
- Raffle: tickets accumulate from purchases or activity, and the winner is drawn and announced automatically.
- Dice: a quick gift that can be limited to customers with no prior purchase or to a specific role.
▸ Service settings
- Brand: shop name (Persian/English), accent colour and logo — all visible in the Mini App.
- Rules: the terms text and its version; bumping the version asks customers to accept again.
- Phone number: require a phone number and optionally restrict it to Iranian numbers.
- Report chat: the group or channel that receives important events (purchases, support messages, errors).
- Maintenance mode: pause purchases with a custom message.
▸ Reports and backup
- Excel/CSV exports for sales, services, wallets and customers.
- Full backup as an encrypted archive (using
BACKUP_PASSWORD). - Restore from a backup file — always take a fresh backup before restoring.
▸ Running several bots from one panel
- In My bots, add a new bot with its token.
- Each bot receives a fully independent data space (its own Durable Object), so users, products and settings never mix.
- Register each bot's webhook from the same screen.
- Selecting a bot switches the whole panel to that bot's data.
▸ What the Mini App is and how to enable it
The Mini App is the graphical shop and account area that opens inside Telegram at https://<your Worker URL>/portal.
Enabling it:
- In Service → Settings, fill in the public URL with your Worker address.
- In BotFather run
/setmenubuttonand point it at/portal, or add a WebApp button to the bot menu. - Customers tap the button and enter the shop without leaving Telegram; their identity is verified through Telegram
initData, so no extra password is needed.
▸ Mini App tabs
| Tab | Purpose |
|---|---|
| Home | Account summary, balance, active services |
| Shop | Buy a plan, apply a discount code |
| My services | Subscription link, usage, renewals |
| Wallet | Top-ups and transaction history |
| Rewards | Wheel, raffle, points |
| Help & support | Written guide plus a live support chat |
▸ In-app support chat (rebuilt)
The support button used to simply throw the customer out of the Mini App and into the bot chat. Now:
- The customer opens Help → Chat with support and sees the whole conversation history.
- They write and send a message right there (up to 2000 characters, limited to 10 messages per minute to prevent spam).
- The message appears instantly in Panel → Support, and if a report chat is configured the staff group is notified too.
- The admin's reply arrives both in that chat thread and as a Telegram message.
- Unread replies show as a red badge on the Help tab, which clears when the thread is opened.
- The view refreshes every 12 seconds, so answers appear without a manual reload.
If the support module is disabled, the customer sees a clear “support is not enabled” message.
▸ Commands and button behaviour
| Command | Result |
|---|---|
/start |
Welcome message and main menu |
/start p_<id> |
Jump straight to a product page (deep link) |
/help |
Help text |
/lang |
Switch language (bilingual mode) |
/news or /khabar |
Nation-wide news: Iran news and world news (translated to Persian), by category |
/rates, /price, /gold, /dollar, /arz |
Live gold, USD, Tether, coin and crypto prices |
/admin or /panel |
The full glass admin panel inside Telegram for the owner (every panel section, edited in place) |
| Support button | Opens a conversation with the admins |
Button behaviour (v3.1+):
- Tapping an inline button edits the same message with new text and buttons, so the chat stays clean.
- Delivered content (files, configs, receipts, payment notices) is still sent as a new message so it remains in the chat history.
- If the original message cannot be edited (too old, or media-based), the bot silently falls back to sending a new message — the user never sees an error.
▸ Routine maintenance
| Task | Frequency | Where |
|---|---|---|
| Full backup | Weekly | Service → Reports & backup |
| Sales Excel export | Monthly | Service → Reports & backup |
| Webhook health check | Monthly | Settings → Webhook management |
| Rotate the panel password | Periodically | Settings → Security |
| Review error logs | Weekly | npx wrangler tail |
Security notes:
- Change the default password on day one.
- Never commit the bot token or gateway keys.
- Keep the media storage chat private.
- Do not rotate
VAULT_KEYwithout a migration plan — previously encrypted data becomes unreadable.
▸ Useful commands and project layout
npm ci # exact dependency install
npm run build # build CSS and static assets
npm run dev # local run on 127.0.0.1:8787
npm test # unit and integration tests
npm run test:ui # browser tests (requires Playwright)
npm run deploy # deploy to Cloudflare
npx wrangler tail # live logsFolder layout:
src/
index.js API routes and the Durable Object
telegram.js Bot logic (messages, buttons, message editing)
bot-api.js Telegram API client
kv.js Data model and support tickets
routes/ Panel routes (users, support, settings …)
services/ Service/VPN module and Mini App API
public/
index.html Panel shell
panel.js UI core
studio.js Bot Studio
services.js Service administration
portal/ Customer Mini App
tests/ Test suite
▸ Common problems and fixes
| Problem | Likely cause | Fix |
|---|---|---|
| The bot does not reply | Webhook not registered | Settings → Webhook management → Set webhook |
| 401 errors in the panel | Session expired | Log out and back in |
| “Invalid token” | Wrong or revoked token | Get a fresh token from BotFather and save it |
| Uploads fail | No storage chat configured | Settings → Files and media |
| Membership is never verified | Bot is not a channel admin | Promote the bot |
| Broadcasts are slow | Telegram rate limits | Lower the batch size, raise the delay |
| Provider credentials are not saved | VAULT_KEY missing |
Add the secret and redeploy |
| The Mini App will not open | Public URL is empty | Service → Settings → Public URL |
| Support messages are not stored | Support module disabled | Check the bot purpose / custom modules |
For the exact server-side error:
npx wrangler tail















