Skip to content

Scenes ​

Scenes isolate portions of your bot's conversation logic into independent routers. When a user enters a scene, only the scene's handlers are active — global handlers are bypassed.

Quick Start ​

typescript
import { Bot, session, Scene, Stage } from 'vibegram';

const bot = new Bot('YOUR_BOT_TOKEN');
bot.use(session());

// Define a scene
const settingsScene = new Scene('settings');

settingsScene.command('theme', ctx => ctx.reply('Choose: light or dark?'));
settingsScene.hears('back', ctx => {
    ctx.reply('Exiting settings.');
    ctx.scene?.leave();
});
settingsScene.on('message', ctx => ctx.reply('You are in settings. Type "back" to exit.'));

// Register and activate
const stage = new Stage([settingsScene]);
bot.use(stage.middleware());

// Enter the scene
bot.command('settings', ctx => ctx.scene?.enter('settings'));

Scene API ​

MethodDescription
ctx.scene?.enter(name)Enter a scene by name
ctx.scene?.leave()Exit the current scene

How It Works ​

  1. When ctx.scene?.enter('name') is called, the session records the current scene
  2. On subsequent updates, the Stage middleware checks if the user is in a scene
  3. If yes, only that scene's handlers run — global handlers are skipped
  4. When ctx.scene?.leave() is called, normal routing resumes

Multiple Scenes ​

typescript
const faqScene = new Scene('faq');
faqScene.on('message', ctx => ctx.reply('FAQ: Ask a question or type "back".'));
faqScene.hears('back', ctx => ctx.scene?.leave());

const contactScene = new Scene('contact');
contactScene.on('message', ctx => ctx.reply('Contact: Send your message or type "back".'));
contactScene.hears('back', ctx => ctx.scene?.leave());

const stage = new Stage([faqScene, contactScene]);
bot.use(stage.middleware());

bot.command('faq', ctx => ctx.scene?.enter('faq'));
bot.command('contact', ctx => ctx.scene?.enter('contact'));

Practical Scenario: Main Menu ​

typescript
const menuScene = new Scene('menu');

menuScene.hears('profile', ctx => ctx.reply('Opening profile...'));
menuScene.hears('orders', ctx => ctx.reply('Opening orders...'));
menuScene.hears('back', ctx => ctx.scene?.leave());

bot.command('menu', ctx => ctx.scene?.enter('menu'));

TIP

Register bot.use(session()) before bot.use(stage.middleware()) — the Stage depends on session data.

Released under the ISC License.