Botledge docs

Botledge runs your Telegram bot on Cloudflare's edge. Telegram pushes each update to your bot's webhook, your code runs, and your bot replies. You write plain JavaScript — nothing to install, no server to keep alive.

Getting started

Three steps:

  1. Open Telegram, message @BotFather, run /newbot, copy the token.
  2. In the dashboard, click + New bot, paste the token, write your code.
  3. Click ▶ Run. Botledge registers the webhook and your bot is live 24/7.
Botledge uses webhooks, not polling. Telegram only sends updates when something happens, which is exactly why free 24/7 hosting is possible.

The bot API

Two ways to handle updates. Both receive a ctx object.

// Runs when someone sends /start
bot.command('start', async (ctx) => {
  await ctx.reply('Hello!');
});

// Runs for every plain text message
bot.on('message', async (ctx) => {
  await ctx.reply('You said: ' + ctx.text);
});

// Runs for button taps
bot.on('callback_query', async (ctx) => {
  await ctx.answer('Got it!');
});

// Runs for every update, whatever the type
bot.on('update', async (ctx) => { /* ... */ });

Events you can listen to: message, callback_query, inline_query, update.

The ctx object

PropertyDescription
ctx.textThe message text.
ctx.chatIdChat id to reply to.
ctx.fromThe sender: { id, first_name, username, … }.
ctx.userIdSender's Telegram id (used for ctx.store).
ctx.commandCommand name (without /) when a command matched.
ctx.argsArray of words after the command.
ctx.updateThe raw Telegram update.
MethodDescription
ctx.reply(text, opts?)Send a message to the chat. opts is any Telegram sendMessage option, e.g. { parse_mode: 'HTML', reply_markup }.
ctx.send(text, opts?)Alias for ctx.reply.
ctx.api(method, params)Call any Telegram Bot API method directly, e.g. ctx.api('sendPhoto', { chat_id, photo }).
ctx.answer(text?, opts?)(callback_query) Answer the button tap.
ctx.edit(text, opts?)(callback_query) Edit the message the button was on.

Storage — ctx.store

Every bot gets a small key/value store backed by SQLite (Cloudflare D1). It's automatically scoped to the user talking to the bot, so scores and settings stay per-user. Values are JSON.

bot.command('points', async (ctx) => {
  const score = (await ctx.store.get('score')) || 0;
  await ctx.store.set('score', score + 1);
  await ctx.reply('Your score: ' + (score + 1));
});

await ctx.store.del('score');   // remove a key

Calling APIs

fetch is available. Call any HTTPS API from your bot:

bot.command('quote', async (ctx) => {
  const res = await fetch('https://api.quotable.io/random');
  const data = await res.json();
  await ctx.reply(data.content);
});

What works & what errors

Your code runs on Cloudflare Workers — a JavaScript edge runtime. Write within those bounds:

✓ Supported

Async/await, promises, fetch(), JSON, dates, the bot API, ctx.store, and any HTTPS service.

✕ Rejected with an error

require(), process, fs, http, child_process, ES import, eval(), infinite loops, and long polling. Botledge catches these and tells you exactly what to change.

When you hit ▶ Run, Botledge compiles your code inside an isolated sandbox before it goes live — so syntax errors and Node-only code are caught immediately with a clear message. Each update then runs within a time limit (about 25 seconds).

Full example — a counter bot

bot.command('start', async (ctx) => {
  await ctx.reply(
    'Hi ' + ctx.from.first_name + '!\\n' +
    'Send /count to add a point, /score to check.'
  );
});

bot.command('count', async (ctx) => {
  const n = ((await ctx.store.get('n')) || 0) + 1;
  await ctx.store.set('n', n);
  await ctx.reply('Count is now ' + n);
});

bot.command('score', async (ctx) => {
  const n = (await ctx.store.get('n')) || 0;
  await ctx.reply('Your score: ' + n);
});

bot.on('message', async (ctx) => {
  await ctx.reply('Unknown command. Try /start');
});

Troubleshooting

My bot doesn't reply. Open the dashboard, check the status pill says live, and read the Logs panel. Make sure you messaged the bot (not someone else's).

Deploy failed. Usually a bad token — copy it again from @BotFather. The token looks like 123456789:ABC….

Error in logs. The log line names the problem — e.g. a Node module you used, or a syntax error. Fix and hit Run again.

Changed my code, nothing happened. Hit Run after saving to re-deploy.


Botledge is free and open source. Built on Cloudflare Workers + D1 + Dynamic Workers.