examples

33 runnable bots in the monorepo under examples/. each one is a private workspace package wired to local source, so it doubles as a live public api smoke test. the table below is generated straight from examples/README.md — it can't drift out of sync with the repo.

terminal
# from a clone of the monorepo
pnpm install

# copy an env template, then add BOT_TOKEN
cp examples/commerce-suite/.env.example examples/commerce-suite/.env

# run with reload
pnpm --filter @yaebal/example-commerce-suite dev
for the full plugin coverage matrix, see examples/readme.md. for a standalone project, use create-yaebal.

playground quick tours

these snippets run in-browser with mock telegram updates, then can switch to live mode with a token.

keyboard.ts
import { InlineKeyboard, callbackData, createBot } from "yaebal";

const choice = callbackData("choice", { value: String });
const bot = createBot(process.env.BOT_TOKEN!);

bot.command("start", (ctx) =>
  ctx.reply("pick a path", {
    reply_markup: new InlineKeyboard()
      .text("ship it", choice.pack({ value: "ship" }))
      .text("wait", choice.pack({ value: "wait" }))
      .build(),
  }),
);

bot.callbackQuery(choice.pattern, async (ctx) => {
  const data = choice.unpack(ctx.callbackQuery.data ?? "");
  await ctx.answer(data?.value === "ship" ? "shipping" : "holding");
  await ctx.editText(`status: ${data?.value ?? "unknown"}`);
});

bot.start();
formatting.ts
import { createBot, html, md } from "yaebal";

const bot = createBot(process.env.BOT_TOKEN!);

bot.command("start", (ctx) =>
  ctx.reply(html`<b>hello</b>, ${ctx.from?.first_name ?? "friend"}
<code>no parse_mode needed</code>`),
);

bot.command("md", (ctx) =>
  ctx.reply(md`**bold**, *italic*, __underline__ and ~~strike~~
> a quoted line`),
);

bot.start();
media-poll.ts
import { createBot } from "yaebal";

const bot = createBot(process.env.BOT_TOKEN!);

bot.command("launch", async (ctx) => {
  await ctx.sendPhoto("https://picsum.photos/seed/yaebal/640/360", {
    caption: "release image by url",
  });

  await ctx.sendPoll("ship today?", ["yes", "hold"]);
});

bot.start();

example catalog

roughly ordered simple → advanced: a bare-core echo bot first, single-plugin demos in the middle, multi-plugin product bots last.

examplepackagefocusruntry it
core-echo@yaebal/example-core-echobare @yaebal/core: middleware, filter narrowing, format, raw typed api.callpnpm --filter @yaebal/example-core-echo dev
basic@yaebal/example-basicwhole-stack tour on yaebal: session, keyboard, callback-data, morda, i18n, scenes, prompt, filters, fmt, retry, throttle, cachepnpm --filter @yaebal/example-basic dev
again@yaebal/example-againawaited retry, retry_after, transient failures, retry metricspnpm --filter @yaebal/example-again dev
ai-chat@yaebal/example-ai-chat@yaebal/ai: streamed replies (drafts in private, edits in groups), conversation memory, AiLimitError handlingpnpm --filter @yaebal/example-ai-chat dev
throttle@yaebal/example-throttleoutbound buckets, priorities, cancellation, scheduler metricspnpm --filter @yaebal/example-throttle dev
broadcast@yaebal/example-broadcasttyped broadcast jobs, pause, resume, cancel, retry, progresspnpm --filter @yaebal/example-broadcast devbroadcast-queue
cron@yaebal/example-cronintervals, cron expressions with per-job tz, retries + backoff, timeoutMs, overlap: "wait", catch-up via a persisted store, ctx.cron, cronAdmin ops commandspnpm --filter @yaebal/example-cron devcron-admin,cron-digest
keyboard@yaebal/example-keyboardinline and reply keyboard builders, every button type, request user/chat/managed botpnpm --filter @yaebal/example-keyboard devkeyboard-callback,reply-keyboard
auto-answer@yaebal/example-auto-answer"deadline" default racing a handler's own alert, fallback ack on a forgotten handler, skipAutoAnswer(), filter()pnpm --filter @yaebal/example-auto-answer devauto-answer-deadline,auto-answer-skip
guards@yaebal/example-guardssafe guard+getChatMember pattern, membership() caching, guardOr answering a denial, bot's own permission check, anonymous admin/ownerpnpm --filter @yaebal/example-guards devguards-private
commands@yaebal/example-commandstyped command registry: localized menus, scopes, aliases, hidden commands, diff-based syncpnpm --filter @yaebal/example-commands dev
ephemeral@yaebal/example-ephemeralephemeral menu commands (is_ephemeral), ctx.replyEphemeral() in groups, handle edits/deletes, wrapEphemeralMessage from a callback, private-chat fallbackpnpm --filter @yaebal/example-ephemeral dev
pagination@yaebal/example-paginationlazy sources (count + limit+1 probing), item buttons with onSelect, typed payload, button() menu morphing and back-navigation, ownership filterpnpm --filter @yaebal/example-pagination devpagination-list,pagination-select
session@yaebal/example-sessionsession v2: dirty-checked saves, file storage, two independent sessions (key + keyBy.user), ttl() fields, clearSession, migrationspnpm --filter @yaebal/example-session devsession-counter,session-v2
simple@yaebal/example-simpletoml route config plus typescript handlerspnpm --filter @yaebal/example-simple dev
onboarding@yaebal/example-onboardingfirst-run product tour, force restart, dismiss, opt-outpnpm --filter @yaebal/example-onboarding dev
feature-flags@yaebal/example-feature-flagspercentage rollout, kill-switch rule, chat-type targeting, multivariate (A/B/n) flag, per-bucket + global overrides with ttl, envProvider, whenFlag branch, flagsAdmin ops commandspnpm --filter @yaebal/example-feature-flags devfeature-flags-override,feature-flags-variants
audit-log@yaebal/example-audit-logcorrelated, redacted-by-default structured logging, applyRedaction, memorySink, chatSink, auditAdmin ops commandspnpm --filter @yaebal/example-audit-log devaudit-log-basic
analytics@yaebal/example-analyticstyped event catalog, autoTrack (commands/callbacks/messages), ctx.identify, context() enricher, multiple adapters, analyticsAdmin ops commandspnpm --filter @yaebal/example-analytics devanalytics-admin,analytics-auto-capture,analytics-track
rich-messages@yaebal/example-rich-messagesrich blocks, markdown/html builders, fake streaming draft, rich message readbackpnpm --filter @yaebal/example-rich-messages devrich-ai
panel@yaebal/example-paneloperator dashboard, media viewer, callbacks, outgoing replies, realtime eventspnpm --filter @yaebal/example-panel dev
commerce-suite@yaebal/example-commerce-suiteshop bot with session cart, i18n, pagination, commands, callback-data, ratelimiterpnpm --filter @yaebal/example-commerce-suite dev
dialog-quest@yaebal/example-dialog-questmorda cockpit, scene wizard, prompt, conversation, session profilepnpm --filter @yaebal/example-dialog-quest devwizard-form,conversation-prompt,conversation-wizard,scenes-buttons,scenes-wizard
state-machine@yaebal/example-state-machinetyped events driving transitions, a guard you can trip interactively, per-state onEnter hooks, reset()pnpm --filter @yaebal/example-state-machine devstate-machine-order
morda-jsx@yaebal/example-morda-jsxjsx screens with hooks: persisted useState/useEffect, useDialogData, widgets (Toggle/Select/Counter/Pagination), onText inputpnpm --filter @yaebal/example-morda-jsx dev
media-studio@yaebal/example-media-studioalbums, file metadata + links, file_id introspection, media cache, svg previews, entity-aware long message splitting + caption strategypnpm --filter @yaebal/example-media-studio dev
modular-router@yaebal/example-modular-routertyped define*() file-based routes (commands/on/hears/use), a nested _guard.ts, syncCommands, watchRoutes hot-reloadpnpm --filter @yaebal/example-modular-router dev
webhook-edge@yaebal/example-webhook-edgeserve() on node, sequentialize + dedupe, setWebhook / getWebhookInfo, secret token, path routingpnpm --filter @yaebal/example-webhook-edge devwebhook-ready
runner-workers@yaebal/example-runner-workersconcurrent polling and worker thread offloadpnpm --filter @yaebal/example-runner-workers dev
testing-lab@yaebal/example-testing-labbot factory plus actor-driven testspnpm --filter @yaebal/example-testing-lab test
inline-search@yaebal/example-inline-searchcore + @yaebal/contexts layering: contextFor, inline.answer(), pagination offset, chosen-result analyticspnpm --filter @yaebal/example-inline-search devinline-mode
payments-stars@yaebal/example-payments-starstelegram stars invoices, pre-checkout approval, successful payment, refundpnpm --filter @yaebal/example-payments-stars devpayments-stars
mini-app@yaebal/example-mini-appHMAC + Ed25519 initData validation, Authorization: tma backend, answerWebAppQuery, web_app_data, direct/attachment-menu linkspnpm --filter @yaebal/example-mini-app dev

patterns to copy

patterncopy from
bare core, no pluginscore-echo
core + contexts by handinline-search
single-file product demobasic
plugin in isolationagain, throttle, keyboard, auto-answer, guards, commands, ephemeral, onboarding, rich-messages, state-machine
production operator toolingbroadcast, panel, webhook-edge, runner-workers
business workflowcommerce-suite, payments-stars, inline-search
multi-step uxdialog-quest, testing-lab
media-heavy workflowmedia-studio
large codebase routingmodular-router, simple

tests

every example has a test script. most examples typecheck as no-network smoke tests; testing-lab runs real actor-driven tests with @yaebal/test.

terminal
# smoke-test every example workspace
pnpm -r --filter "./examples/*" run test

# run the actor-driven test example only
pnpm --filter @yaebal/example-testing-lab test
plugin packages keep focused tests under packages/*/src/*.test.ts; examples prove the public imports still compose in real bot shapes.