Skip to main content

Menu Nodes

Build interactive menus, wizards, and navigation systems. These nodes handle user choices, pagination, multi-step forms, and complex menu hierarchies.


Why Use Menu Nodes?​

Menu nodes provide a structured way to build interactive experiences:

  • ✅ User-Friendly: Visual buttons instead of text commands
  • ✅ State Management: Auto-tracks menu navigation
  • ✅ Built-in Navigation: Back buttons, breadcrumbs
  • ✅ Pagination: Handle large lists elegantly

Example of multi-level menu with back navigation


📋 Show Menu (menu.show)​

The core menu node that displays options and handles user selection.

Configuration​

SettingDescription
MessageText to show above buttons
ItemsArray of menu options
ColumnsButtons per row (1-3)
AllowBackShow "← Back" button
ParseModeMarkdown/HTML formatting

Item Format​

Each menu item is an object:

{
"label": "đŸ“Ļ View Products",
"data": "show_products",
"url": "https://shop.com" // Optional link
}

Dynamic Outputs​

The node creates output sockets for each menu item:

  • One output per item (based on data field)
  • Back output (if enabled)
  • Cancel output (optional)

Example: Main Menu​

menu.show:
Message: "Welcome! What would you like to do?"
Items: [
{ label: "đŸ›ī¸ Browse Products", data: "products" },
{ label: "📞 Contact Support", data: "support" },
{ label: "â„šī¸ About Us", data: "about" }
]
Columns: 2

Outputs:
products → [Show ProductsCatalog]
support → [Start Support Chat]
about → [Send About Info]

[Screenshot: menu.show node showing 3 items and their corresponding output sockets]


🧙 Multi-Step Wizard (menu.wizard)​

Your all-in-one solution for collecting information step-by-step — like a guided form that remembers where users left off!

Why Use Wizards?​

Perfect for:

  • 📝 Registration Forms — Collect name, email, preferences
  • 🛒 Checkout Flows — Shipping address, payment, confirmation
  • 📋 Surveys — Multi-question questionnaires
  • âš™ī¸ Onboarding — Walk new users through setup
  • đŸŽĢ Booking Systems — Date, time, guest count

Configuration​

SettingDescription
StepsArray of step configurations (see below)
SaveToVarSave collected data to this variable
MaxRetriesGlobal retry limit (can override per-step)
AllowBackShow "← Previous Step" button

📋 Step Configuration​

Each step has these options:

FieldWhat It DoesExample
idUnique step name"email_step"
titleQuestion to ask"What's your email?"
typeInput type (see types below)"email"
requiredMust answer to continue?true
validationCustom rule (expression)"len(value) > 5"
error_messageShow if validation fails"Email must be valid"
show_ifOnly show if condition met"plan == 'premium'"
next_stepJump to specific step"payment_step"
max_retriesRetry limit for this step3
defaultPre-fill value"United States"
optionsChoices (for select/confirm)See examples below

🎨 Input Types​

TypeWhat It AcceptsExample Use
textAny textName, address
numberNumbers onlyAge, quantity
emailValid email formatuser@example.com
phonePhone number+1-555-0100
urlWeb linkhttps://example.com
selectMultiple choicePlan selection
confirmYes/NoAgree to terms?
photoUser uploads imageProfile picture

Outputs​

OutputDescriptionType
CompleteAll steps finishedFlow
CancelledUser cancelled wizardFlow
FormDataAll collected answersObject
CurrentStepCurrent step numberNumber
TotalStepsTotal step countNumber
ErrorTextError message if anyString

📚 Complete Examples​

Example 1: Simple Registration​

{
"steps": [
{
"id": "name",
"title": "👋 What's your name?",
"type": "text",
"required": true
},
{
"id": "email",
"title": "📧 Enter your email:",
"type": "email",
"required": true,
"error_message": "Please enter a valid email address"
},
{
"id": "age",
"title": "🎂 How old are you?",
"type": "number",
"required": true,
"validation": "value >= 18",
"error_message": "You must be 18 or older"
}
],
"save_to_var": "var.user_registration"
}

Result: When complete, var.user_registration contains:

{
"name": "John Doe",
"email": "john@example.com",
"age": 25
}

Example 2: Product Order with Branching​

{
"steps": [
{
"id": "product",
"title": "đŸ›ī¸ What would you like to order?",
"type": "select",
"options": [
{ "label": "đŸ–Ĩī¸ Laptop", "value": "laptop" },
{ "label": "📱 Phone", "value": "phone" },
{ "label": "⌚ Watch", "value": "watch" }
]
},
{
"id": "laptop_spec",
"title": "đŸ’ģ Choose RAM:",
"type": "select",
"show_if": "product == 'laptop'",
"options": [
{ "label": "8GB - $999", "value": "8gb" },
{ "label": "16GB - $1299", "value": "16gb" }
]
},
{
"id": "phone_color",
"title": "🎨 Choose color:",
"type": "select",
"show_if": "product == 'phone'",
"options": [
{ "label": "Black", "value": "black" },
{ "label": "White", "value": "white" },
{ "label": "Blue", "value": "blue" }
]
},
{
"id": "confirm",
"title": "✅ Confirm your order?",
"type": "confirm"
}
]
}

How it works:

  1. User selects "Laptop"
  2. Wizard shows laptop_spec (because show_if condition is true)
  3. Wizard SKIPS phone_color (because show_if is false)
  4. Goes to confirm

Example 3: Survey with Smart Branching​

{
"steps": [
{
"id": "satisfied",
"title": "😊 Are you satisfied with our service?",
"type": "select",
"options": [
{ "label": "😃 Very Satisfied", "value": "very" },
{ "label": "🙂 Satisfied", "value": "ok" },
{ "label": "😐 Unsatisfied", "value": "bad" }
]
},
{
"id": "what_good",
"title": "đŸ’Ŧ What did you like most?",
"type": "text",
"show_if": "satisfied == 'very' || satisfied == 'ok'"
},
{
"id": "what_wrong",
"title": "💔 What went wrong?",
"type": "text",
"show_if": "satisfied == 'bad'",
"required": true
},
{
"id": "recommend",
"title": "Would you recommend us?",
"type": "confirm"
}
]
}

Smart flow:

  • Happy customers → "What did you like?"
  • Unhappy customers → "What went wrong?"
  • Everyone → "Would you recommend?"

✨ Advanced Features​

🔄 Retry Handling​

Set retry limits to prevent frustration:

{
"id": "password",
"title": "🔒 Create a strong password:",
"type": "text",
"validation": "len(value) >= 8",
"error_message": "Password must be at least 8 characters",
"max_retries": 3
}

After 3 failed attempts → Goes to Cancelled output


đŸŒŗ Dynamic Navigation​

Jump to different steps based on answers:

{
"id": "account_type",
"title": "Choose account type:",
"type": "select",
"options": [
{ "label": "Personal", "value": "personal" },
{ "label": "Business", "value": "business" }
],
"next_step": "business_info" // Skip to business questions
}

💾 Accessing Collected Data​

After the wizard completes, access the data:

FormData output → {
"name": "John",
"email": "john@example.com",
"plan": "premium"
}

In templates:

Welcome {{FormData.name}}!
Your plan: {{FormData.plan}}

In variables: If you set save_to_var: "var.signup", then:

{{var.signup.name}}
{{var.signup.email}}

đŸŽ¯ Best Practices​

1. Keep It Short​

❌ Don't: 20-step registration ✅ Do: 3-5 essential questions

2. Show Progress​

The wizard automatically shows:

Step 2 of 4

3. Use Validation Early​

{
"type": "email", // ← Validates email format automatically
"validation": "not includes(value, 'spam')" // ← Extra custom check
}

4. Smart Branching​

Only ask relevant questions:

{
"show_if": "country == 'USA'", // ← Only for US users
"title": "What's your state?"
}

5. Provide Defaults​

{
"id": "country",
"default": "United States" // ← Pre-filled
}

🚀 Real-World Use Cases​

Hotel Booking​

1. Check-in date
2. Check-out date
3. Number of guests
4. Room type (economy/deluxe/suite)
5. Breakfast? (yes/no)
6. Confirm booking

Event Registration​

1. Full name
2. Email
3. Company name
4. Meal preference (vegetarian/non-veg/vegan)
5. T-shirt size (if attending in-person)
6. Confirm registration

Support Ticket​

1. Issue category (billing/technical/other)
2. Describe issue
3. Upload screenshot (optional)
4. Priority (low/medium/high)
5. Submit ticket


📄 Paginated List (menu.paginated_list)​

Display large lists with navigation buttons (Next/Previous).

Configuration​

SettingDescription
ItemsArray of all items
PageSizeItems per page (default: 5)
ItemTemplateHow to format each item
HeaderMessage above list

Outputs​

OutputDescription
ItemSelectedUser clicked an item
SelectedItemThe selected item data
SelectedIndexItem's array index

Example: Product Catalog​

menu.paginated_list:
Items: [
{ name: "Laptop", price: 999 },
{ name: "Mouse", price: 25 },
{ name: "Keyboard", price: 75 },
... 50 more products
]
PageSize: 5
ItemTemplate: "{{name}} - ${{price}}"
Header: "đŸ›ī¸ Our Products (Page {{page}}/{{total_pages}})"

Shows:
Page 1/10
đŸ›ī¸ Our Products

Laptop - $999
Mouse - $25
Keyboard - $75
Monitor - $350
Webcam - $120

[â—€ī¸ Previous] [Next â–ļī¸]

[Screenshot: Paginated list showing Page 2 of 5 with navigation buttons]

Use Cases:

  • Product catalogs
  • Search results
  • User lists
  • Content browse

🔀 Menu Router (menu.router)​

Route to different submenus based on user selection, creating hierarchical navigation.

Configuration​

SettingDescription
RoutesMap of data → submenu
DefaultRouteFallback menu

Example: Multi-level Navigation​

Main Menu
↓
[menu.router]
products → Product Categories Menu
support → Support Options Menu
settings → Settings Menu

Use Case: Complex navigation trees (e-commerce, help centers)


âŦ…ī¸ Navigate Back (menu.navigate_back)​

Return to the previous menu in the navigation stack.

Configuration​

SettingDescription
MessageOptional text when going back

How It Works​

BotGami automatically tracks menu navigation history. This node pops the stack:

User flow:
Main → Products → Category → Item
↑
[Navigate Back]
Goes back to: Category

Example: Breadcrumb Navigation​

Every menu.show has AllowBack: true
↓
Each "Back" output connects to menu.navigate_back
↓
Automatic breadcrumb trail

[Screenshot: Menu showing "← Back" button with breadcrumb path]


🔄 Reset Menu (menu.reset)​

Clear navigation history and return to a specific menu (usually main).

Configuration​

SettingDescription
TargetMenuMenu ID to reset to
MessageOptional reset message

Example: Return to Main​

User finishes checkout
↓
[menu.reset → main_menu]
↓
"✅ Order complete! Returning to main menu..."

Use Cases:

  • After completing a workflow
  • Timeout/idle cleanup
  • Error recovery

❓ Confirmation Dialog (menu.confirm)​

Simple Yes/No confirmation prompt.

Configuration​

SettingDescription
MessageQuestion to ask
YesLabelCustom "Yes" button text
NoLabelCustom "No" button text

Outputs​

OutputDescription
YesUser confirmed
NoUser declined

Example: Delete Confirmation​

menu.confirm:
Message: "đŸ—‘ī¸ Delete this item? This cannot be undone."
YesLabel: "✅ Yes, delete it"
NoLabel: "❌ No, keep it"

Yes → [Execute deletion]
No → [Cancel action]

[Screenshot: Confirmation dialog with styled Yes/No buttons]


🔍 Search Menu (menu.search)​

Let users search through a list and select results.

Configuration​

SettingDescription
SearchableFieldsWhich fields to search
ItemsData source array
ResultTemplateHow to display results
MaxResultsLimit displayed results
menu.search:
Items: [ ...array of users ]
SearchableFields: ["name", "email"]
ResultTemplate: "{{name}} ({{email}})"
MaxResults: 10

User types: "john"
↓
Shows: John Doe (john@example.com)
John Smith (jsmith@example.com)

Use Cases:

  • User directory
  • Product search
  • Content discovery

Toggle Switch (menu.toggle)​

ON/OFF switch for settings.

Configuration​

SettingDescription
VariableWhich var to toggle
OnLabelText when ON
OffLabelText when OFF

Example: Notifications Setting​

menu.toggle:
Variable: "var.notifications_enabled"
OnLabel: "🔔 Notifications ON"
OffLabel: "🔕 Notifications OFF"

Current state shown with appropriate icon/label
User clicks → Value toggles

📝 Dynamic Menu from Data (menu.from_data)​

Generate menu items dynamically from an array or API response.

Configuration​

SettingDescription
DataSourceArray or object to generate from
LabelTemplateHow to format button labels
DataTemplateWhat to put in callback data

Example: Category Menu from Database​

[HTTP GET /api/categories]
↓ Response: [
{ id: 1, name: "Electronics" },
{ id: 2, name: "Clothing" },
{ id: 3, name: "Books" }
]
↓
[menu.from_data]
DataSource: (connected to HTTP response)
LabelTemplate: "{{name}}"
DataTemplate: "cat_{{id}}"
↓
Generates menu:
đŸˇī¸ Electronics (callback: cat_1)
đŸˇī¸ Clothing (callback: cat_2)
đŸˇī¸ Books (callback: cat_3)

[Screenshot: Dynamic menu generated from API data]

Use Cases:

  • Database-driven menus
  • Dynamic catalogs
  • User-generated content lists

Best Practices​

1. Keep Menus Simple​

  • Max 6-8 buttons per menu
  • Use pagination for more
  • Clear, concise labels

2. Always Provide "Back"​

menu.show:
AllowBack: true

Each menu connects its Back output to menu.navigate_back

3. Use Wizards for Multi-Step​

Don't build complex flows manually — use menu.wizard:

❌ manual.question → question → question → ...
✅ menu.wizard (automatic state, navigation, validation)

4. Icons in Labels​

Makes menus more visual:

Items: [
{ label: "đŸ›ī¸ Shop", data: "shop" },
{ label: "đŸ“Ļ Orders", data: "orders" },
{ label: "âš™ī¸ Settings", data: "settings" }
]

5. Handle Menu Timeout​

[menu.show]
↓ (after 5 minutes)
[menu.reset]
Message: "Session expired. Returning to main menu."

Common Patterns​

Pattern 1: Main Menu → Submenus​

[Main Menu]
├─ products → [Product Categories Menu]
│ ├─ electronics → [Electronics List]
│ └─ clothing → [Clothing List]
├─ support → [Support Menu]
└─ settings → [Settings Menu]

Pattern 2: List → Detail → Action​

[Paginated Product List]
→ Select Item
→ [Product Detail Menu]
├─ Add to Cart
├─ View Specs
└─ ← Back to List

Pattern 3: Wizard → Confirmation → Result​

[Registration Wizard]
→ Collect: name, email, plan
→ [Confirmation: "Create account with these details?"]
├─ Yes → [Create Account] → [Success Menu]
└─ No → [Back to Wizard]

Quick Reference​

NodeUse For
menu.showBasic choice menus
menu.wizardMulti-step forms
menu.paginated_listLong lists (products, search)
menu.routerHierarchical navigation
menu.navigate_backBack button behavior
menu.resetReturn to main/start
menu.confirmYes/No dialogs
menu.searchSearchable lists
menu.toggleON/OFF settings
menu.from_dataDynamic menus from data

Next Steps​