Skip to content
neverlanePublic

About

yet another tElegram bot api library for node.js (deno and bun TOO!!!!!!!!!!!!!!!)

Resources

Stars

8 stars

Watchers

0 watching

Forks

Repository files navigation

yaebal logo

yet another telegram bot api library
type-safe · chainable · plugin-first · batteries included

docs · playground · npmx

npm version github stars license

yaebal is a type-safe telegram bot framework for typescript. build your bot as one chain: derive, decorate, install, guard, filters and plugins all carry the context type forward, so handlers see exactly what earlier steps added.

import { InlineKeyboard, callbackData, createBot, html, session } from "yaebal";

const vote = callbackData("vote", { id: Number });

const bot = createBot(process.env.BOT_TOKEN!)
  .install(session({ initial: () => ({ count: 0 }) }))
  .derive((ctx) => ({ name: ctx.from?.first_name ?? "friend" }));

bot.command("start", (ctx) =>
  ctx.reply(html`<b>hey ${ctx.name}</b>, pick one`, {
    reply_markup: new InlineKeyboard()
      .text("yes", vote.pack({ id: 1 }))
      .text("no", vote.pack({ id: 2 }))
      .build(),
  }),
);

bot.on("message:text", (ctx) => ctx.reply(`typed text: ${ctx.text}`));

bot.on("callback_query:data", (ctx) => {
  const data = vote.unpack(ctx.callbackQuery.data);
  if (data) ctx.session.count += data.id;
  return ctx.answer(`count: ${ctx.session.count}`);
});

await bot.start();

why yaebal

  • Bot extends Composer, so there is one middleware engine instead of a bot/router split.
  • filter queries such as on("message:text") narrow the handler context without casts.
  • generated contexts give update-specific shortcuts such as ctx.react, ctx.answer, and ctx.editText.
  • first-party plugins cover sessions, keyboards, callback data, formatting, webhooks, retries, testing, routing and more.
  • explicit plugin dependencies make wrong install order a type error instead of a production surprise.

install

pnpm add yaebal

or scaffold a fresh bot — templates, plugins, a docker/fly/railway/cloudflare/vercel deploy target and a ci workflow are all one flag away (see create a bot):

pnpm create yaebal

choose your path

need start here
build your first bot getting started
remember the api fast cheat sheet
understand context type flow typed examples
ship webhooks or edge bots webhooks & deploy
harden a production bot production guide
debug common bot issues troubleshooting
move from another framework migration guides
build payments, inline mode or mini apps telegram guides
ask an ai assistant to write yaebal code llms.txt

if yaebal saves you time, star the repo. it helps people find a young project.

examples

runnable bots live under examples/. clone the repo, drop a token in .env, and run one package. the full plugin coverage matrix is in examples/readme.md.

example what it shows run
core-echo bare @yaebal/core: middleware, filter narrowing, format, raw typed api.call pnpm --filter @yaebal/example-core-echo dev
tgcloud echo bot with a per-chat counter, bundled into telegram serverless handlers pnpm --filter @yaebal/example-tgcloud dev
basic whole-stack tour on yaebal: keyboard, callback-data, session, morda, i18n, scenes, prompt, filters, fmt, retry, throttle pnpm --filter @yaebal/example-basic dev
again awaited retry on structured retry_after and transient 5xx pnpm --filter @yaebal/example-again dev
ai-chat llm chat on @yaebal/ai: streamed draft replies, per-user memory, polite rate limits pnpm --filter @yaebal/example-ai-chat dev
throttle outbound scheduler with buckets, priority, cancellation and metrics pnpm --filter @yaebal/example-throttle dev
broadcast typed broadcast jobs with progress, retry, pause, resume and cancel pnpm --filter @yaebal/example-broadcast dev
keyboard every keyboard button type, dynamic grids, reply keyboards and request buttons pnpm --filter @yaebal/example-keyboard dev
commands typed command registry: localized menus, scopes, aliases, hidden commands, diff sync pnpm --filter @yaebal/example-commands dev
ephemeral ephemeral commands, rich/media edits, callback overlays, private-chat fallback pnpm --filter @yaebal/example-ephemeral dev
pagination lazy paginated lists, item buttons with onSelect, typed payload, menu morphing, ownership filter pnpm --filter @yaebal/example-pagination dev
session session v2: dirty-checked saves, file storage, two independent sessions, ttl() fields, clearSession, migrations pnpm --filter @yaebal/example-session dev
simple toml routes with a typescript handler registry pnpm --filter @yaebal/example-simple dev
onboarding first-run product tour with typed flow controls and opt-out state pnpm --filter @yaebal/example-onboarding dev
rich-messages rich block builders, attached uploads, structured drafts and readback pnpm --filter @yaebal/example-rich-messages dev
panel operator dashboard with media viewer, keyboards, callbacks and events pnpm --filter @yaebal/example-panel dev
commerce-suite shop bot: cart session, i18n, pagination, callback data, command registry, ratelimiter pnpm --filter @yaebal/example-commerce-suite dev
dialog-quest morda cockpit, scenes, prompt, conversation and session profile pnpm --filter @yaebal/example-dialog-quest dev
state-machine typed events driving transitions, a guard you can trip interactively, per-state onEnter hooks, reset() pnpm --filter @yaebal/example-state-machine dev
morda-jsx jsx dialog screens: persisted hooks, dialog data, widgets, free-text input pnpm --filter @yaebal/example-morda-jsx dev
media-studio albums, file metadata + links, file_id introspection, media cache, svg previews, entity-aware splitting pnpm --filter @yaebal/example-media-studio dev
modular-router typed define*() file-based routes, a nested guard, syncCommands, watchRoutes hot-reload pnpm --filter @yaebal/example-modular-router dev
webhook-edge serve() on node, sequentialize + dedupe, secret token, setWebhook / getWebhookInfo pnpm --filter @yaebal/example-webhook-edge dev
runner-workers concurrent polling plus worker thread offload pnpm --filter @yaebal/example-runner-workers dev
testing-lab bot factory with real actor-driven node:test coverage pnpm --filter @yaebal/example-testing-lab test
inline-search core + @yaebal/contexts by hand: contextFor, inline.answer(), offset pagination, chosen-result analytics pnpm --filter @yaebal/example-inline-search dev
payments-stars telegram stars invoices, pre-checkout approval, successful payment and refund pnpm --filter @yaebal/example-payments-stars dev
mini-app HMAC + Ed25519 initData validation, Authorization: tma backend demo, answerWebAppQuery, link builders pnpm --filter @yaebal/example-mini-app dev
audit-log correlated, redacted-by-default logging, applyRedaction, memorySink, chatSink, auditAdmin ops commands pnpm --filter @yaebal/example-audit-log dev

plugins

package what
@yaebal/again awaited retry on structured retry_after / transient 5xx
@yaebal/ai llm superpowers: ctx.ai.replyStream() with native draft streaming, memory, limits, any provider — plus an mcp server and agent installer for ai-assisted development
@yaebal/session typed sessions: dirty-checked saves, lazy mode, multi-session, ttl fields, migrations
@yaebal/sklad zero-dep storage adapters: memory (ttl/lru), redis, sqlite, cloudflare kv, file
@yaebal/cache ctx.cache.get/set/wrap — ttl memoization, stale-while-revalidate, sliding expiry, negative caching, prefix invalidation, typed key catalog
@yaebal/feature-flags ctx.flags.isEnabled(key)/getVariant(key) — typed boolean & A/B/n flags, telegram-native targeting, global overrides, guard/whenFlag, admin commands, LaunchDarkly/GrowthBook/env adapters
@yaebal/keyboard fluent inline and reply keyboard builders
@yaebal/callback-data typed callback_data pack / unpack
@yaebal/payments typed invoice builder (stars / external providers), pre-checkout & successful-payment hooks, star subscriptions
@yaebal/mini-app Telegram Mini Apps server protocol: HMAC + Ed25519 (third-party) initData validation, typed parser & test signer, Authorization: tma header helper, answerWebAppQuery, WebAppInfo/deep-link url generator
@yaebal/link-preview fluent builder for link_preview_options
@yaebal/inline-results typed builders for every InlineQueryResult / InputMessageContent variant
@yaebal/auto-answer auto-clears the callback-query loading spinner, no manual answerCallbackQuery call
@yaebal/typing ctx.typing(fn) keeps the "is typing…" indicator alive for an async call, no manual sendChatAction
@yaebal/ephemeral ctx.replyEphemeral() — answer in a group so only the asker sees it: typed edit/delete handle over ephemeral messages, private-chat fallback, expiry policies
@yaebal/filters composable, type-narrowing update filters: and/or/not, deep links, async
@yaebal/guards reusable bot.guard() predicates: isAdmin, hasPermission, cached membership(), guardOr, anonymous-admin aware
@yaebal/fmt html / md tagged templates with auto-escaping
@yaebal/rich sendRichMessage / sendRichMessageDraft: block builder and streaming drafts
@yaebal/morda dialogs engine and jsx/hooks for telegram ui
@yaebal/i18n typed ctx.t (keys + params), Intl plurals, language_code detection
@yaebal/scenes durable wizards: typed state, ask() validation, navigation, sub-scenes, ttl
@yaebal/state-machine declarative finite-state machines: typed events, guarded transitions, onEnter/onLeave hooks
@yaebal/onboarding declarative first-run tutorials with inline controls
@yaebal/conversation await-style multi-step dialogs — coroutine by default, durable replay engine opt-in
@yaebal/prompt ask a question, handle the next message
@yaebal/router typed file-based routing — define*() routes, load-time validation, nested guards, watchRoutes hot-reload
@yaebal/toml declarative toml routes with a handler registry
@yaebal/throttle priority outbound scheduler with global/private/group buckets
@yaebal/files inspect, link, stream and download files; local Bot API server aware
@yaebal/file-id parse and re-serialize file_id / file_unique_id strings (zero deps)
@yaebal/ratelimiter drop updates from users who spam
@yaebal/broadcast typed broadcast jobs with storage, retry, progress and controls
@yaebal/cron typed cron jobs: timezones, retries, catch-up, distributed locks, and a chat-native admin surface
@yaebal/panel framework-agnostic operator panel with media, keyboards and event timeline
@yaebal/analytics typed ctx.track(event, properties) with auto-capture, privacy controls, an in-chat admin surface, and pluggable sinks: posthog, plausible, sqlite, clickhouse, http
@yaebal/sentry sentry error tracking — an isolation scope per update, captured handler failures, update and api breadcrumbs
@yaebal/otel opentelemetry tracing — a span per update, a child span per bot api call and retry, ctx.otel.record
@yaebal/audit-log correlated, redacted-by-default audit logging — sinks, formatters, filters, sampling, chatSink, auditAdmin
@yaebal/web webhooks on any runtime — edge, node servers, serverless, fetch frameworks; adapters, sequentialize, dedupe, lifecycle
@yaebal/tgcloud build a bot into telegram serverless handlers — one self-contained bundle per update type, bot api calls served by sdk instead of http
@yaebal/runner concurrent long-polling for scale
@yaebal/media-group collect albums into one handler call or a ctx.mediaGroup pass-through
@yaebal/media-cache upload once, reuse the file_id — self-heals when telegram rejects it
@yaebal/hydrate hydrated api results — the returned Message gains editText/delete/pin/forward/copy/react
@yaebal/split long text as multiple messages — entity-aware splits, partial-failure reports
@yaebal/commands one registry for handlers and the / menu — localized, scoped, diff-synced
@yaebal/pagination paginated lists over any source — lazy fetch, item buttons, typed payload
@yaebal/preview render telegram-style chats to svg — reply quotes, reactions, link previews, custom themes
@yaebal/workers typed worker_threads pool — queueing, timeouts, aborts, crash recovery

repository map

About

yet another tElegram bot api library for node.js (deno and bun TOO!!!!!!!!!!!!!!!)

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages