Бот за 30 секунд
npm create gramio@latest разворачивает полный проект — TypeScript, ORM, линтинг, плагины, Docker — на ваш выбор.
Типобезопасно · Мультирантайм · Расширяемо
import { Bot, format, bold, link } from "gramio";
const bot = new Bot(process.env.BOT_TOKEN as string)
.command("start", (ctx) =>
ctx.send(
format`${bold`Привет, ${ctx.from?.firstName ?? "незнакомец"}!`}
Добро пожаловать в ${link("GramIO", "https://gramio.dev")} — создавайте Telegram-ботов правильно.`,
),
)
.onError(({ kind, error }) => console.error(kind, error))
.start();import { Bot, InlineKeyboard, CallbackData } from "gramio";
const voteData = new CallbackData("vote").string("choice");
const bot = new Bot(process.env.BOT_TOKEN as string)
.command("poll", (ctx) =>
ctx.send("Нравится ли вам GramIO?", {
reply_markup: new InlineKeyboard()
.text("Да ✅", voteData.pack({ choice: "yes" }))
.text("Конечно 🔥", voteData.pack({ choice: "yes2" })),
}),
)
.callbackQuery(voteData, (ctx) => {
ctx.queryData.choice; // ^? string
return ctx.answer();
})
.start();import {
defineI18n,
type LanguageMap,
type ShouldFollowLanguage,
} from "@gramio/i18n";
import { Bot, format, bold } from "gramio";
const en = {
welcome: (name: string) => format`Hello, ${bold(name)}!`,
items: (n: number) => `You have ${n} item${n === 1 ? "" : "s"}`,
} satisfies LanguageMap;
const ru = {
welcome: (name: string) => format`Привет, ${bold(name)}!`,
items: (n: number) => `У вас ${n} предмет${n === 1 ? "" : "ов"}`,
} satisfies ShouldFollowLanguage<typeof en>; // ключи и сигнатуры должны совпадать
const i18n = defineI18n({ primaryLanguage: "en", languages: { en, ru } });
const bot = new Bot(process.env.BOT_TOKEN as string)
.derive((ctx) => ({
t: i18n.buildT(ctx.from?.language_code ?? "en"),
}))
.command("start", (ctx) =>
ctx.send(ctx.t("welcome", ctx.from?.firstName ?? "незнакомец")),
)
.start();import { Bot } from "gramio";
import { Scene, scenes } from "@gramio/scenes";
import { redisStorage } from "@gramio/storage-redis";
import { Redis } from "ioredis";
const registerScene = new Scene("register")
.step("message", (ctx) => {
if (ctx.scene.step.firstTime) return ctx.send("Как вас зовут?");
return ctx.scene.update({ name: ctx.text });
})
.step("message", (ctx) => {
if (ctx.scene.step.firstTime)
return ctx.send(`Привет, ${ctx.scene.state.name}! Ваш email?`);
return ctx.scene.update({ email: ctx.text });
})
.step("message", (ctx) =>
ctx.send(
`Зарегистрирован: ${ctx.scene.state.name} — ${ctx.scene.state.email} ✅`,
),
);
const bot = new Bot(process.env.BOT_TOKEN as string)
.extend(scenes([registerScene], { storage: redisStorage(new Redis()) }))
.command("register", (ctx) => ctx.scene.enter(registerScene))
.start();import { Bot } from "gramio";
import { Composer } from "@gramio/composer";
// Общий middleware — типизированный контекст доступен в каждом модуле
const withUser = new Composer()
.derive(async (ctx) => ({
user: await db.getUser(ctx.from?.id ?? 0),
}))
.as("scoped");
// Feature-модуль — guard и команды в одной цепочке
const adminRouter = new Composer()
.extend(withUser)
.guard((ctx) => ctx.user.role === "admin")
.command("ban", (ctx) => ctx.send(`Заблокирован — ${ctx.user.name}`))
.command("stats", (ctx) => ctx.send("Статистика..."));
const bot = new Bot(process.env.BOT_TOKEN as string)
.extend(withUser) // ctx.user — типизирован везде ниже
.extend(adminRouter) // withUser внутри → дедуплицируется, запускается один раз
.command(
"profile",
(
ctx, // без guard — выполняется для всех
) => ctx.send(`Привет, ${ctx.user.name}!`),
// ^? полностью типизировано
)
.start();Bot API 9.5, дебют Rate Limiter, конвертер HTML в Telegram, суперсилы Composer — 23 февраля – 2 марта 2026
Поддержка Bot API 9.5 во всей экосистеме (теги участников, сущности date_time). Новый плагин @gramio/rate-limit с макросным троттлингом. @gramio/format v0.5.0 — htmlToFormattable(). @gramio/composer получает EventContextOf, ContextOf, defineComposerMethods и систему макросов.
::: pm-create gramio@latest ./bot :::