Menus and the data-driven engine
Every menu shown to telnet / SSH / rlogin users is stored in the
database and editable from the web. There's no source code change
needed to add, remove, rename, or relink anything.
Where to edit
Admin → BBS Menus (/admin/bbs-menus/).
You'll see:
- Menu tree — entry-point menus and which submenus they goto
- All menus table with quick edit/delete
Anatomy of a menu
A menu has:
| field | meaning |
|---|---|
name |
unique key (e.g. main, games, sysop_tools) |
title |
shown in the auto-rendered banner |
prompt |
text before the input cursor (Choice:) |
ansi_screen |
raw ANSI/CP437 art shown above the menu (optional) |
is_default |
this is the entry point after login |
min_access |
hide menu from users below this access level |
Menu items
Each item has:
hotkey— single character or short sequencelabel— visible textaction_type— what to do when pickedaction_args— passed to the actionmin_access— hide if user is below thissort_order,is_visible
Action types
| action | args | what it does |
|---|---|---|
goto |
name of another menu | jump to another menu |
door |
Game.id | launch a registered door game |
exec |
shell cmd or JSON | run an external program (see doc 5) |
ansi |
slot name (welcome / weather_intro / ...) | display a sysop-defined ANSI screen |
boards |
— | message boards UI |
pm |
— | PM inbox |
pm_send |
— | compose new PM |
imsg |
— | Inter-BBS Instant Message (MSP) inbox |
imsg_send |
— | compose new Inter-BBS Instant Message |
bulletins |
— | bulletins |
echo |
— | echomail areas |
echo_post |
— | compose echomail |
files |
— | file library |
who |
— | who's online |
multinode |
— | interactive multinode chat |
oneliners |
— | last 10 callers + recent one-liners |
chat |
— | chat menu (IRC / shoutbox) |
rss |
— | RSS reader |
ebooks |
— | ebook reader (Gutenberg) |
wall |
— | graffiti wall |
games |
— | game center |
dialout |
— | dial out to other BBSes |
page |
— | page sysop |
profile |
— | view profile |
edit_prof |
— | edit profile |
passwd |
— | change password |
sysop |
— | sysop tools (admin only) |
logoff |
— | end session |
A couple of action types in more detail
Most action types are self-explanatory from the table above, but two
are easy to underestimate from a one-line description:
wall— the graffiti wall (anetbbs/features/wall.py). A
shared, paginated bulletin board of short (1-2 line) messages any
user can post to, rendered as an ANSI box that adapts its width to
the caller's terminal (79 cols on standard 80-col, up to 131 wide).
Posts support Synchronet/Mystic-style|XXpipe color codes, with
an ASCII-only fallback for terminals that can't render CP437
box-drawing characters. Sysops get an extra[D]eloption to remove
a post by ID. Not networked or moderated beyond that — it's a purely
local, lightweight "who was here" wall, distinct from boards,
echomail, and the shoutbox.ebooks— the ebook reader (slugebooks,anetbbs/web/ebooks.py
for the web version,show_ebooks()inanetbbs/features/bbs_ui.py
for the terminal version — both share the same backend). Lets users
search and read free public-domain books from Project Gutenberg via
Gutendex (gutendex.com, a community JSON search API over Gutenberg's
catalog), plus a curated "classics" shelf for browsing without
searching first. Book text is fetched once per title and cached
forever (EbookCache); per-user bookmarks and reading history
persist across sessions. The terminal reader offers the same
classics/search/history/bookmarks flow as the web version, paginated
for the terminal. This action is gated per-Gamerow by a
terminal_enabledtoggle (Admin → Games) independent of the web
version's ownweb_enabledtoggle, so a sysop can offer one without
the other.
Adding a sub-menu
Click any menu's edit page → "Add a sub-menu (one click)" card.
Fill in:
- New menu key (games_arcade)
- Title (Arcade Games)
- Hotkey on this menu (A)
- Label (Arcade)
It creates the child menu, auto-adds a Q key on the child to come
back, and links from the parent. You can deep-nest as far as you
like.
Tips
- The
min_accessfield on items + menus implements
Mystic/Synchronet-style tiers. Set a user'saccess_levelin
Admin → Users → Manage. - Setting
is_default=Trueon a menu other thanmainlets you
override the entry point. - The "Add sample items" button on the menu list adds a working
weather door (curl wttr.in) + an ANSI replay so you can verify
execandansiactions work without writing your own.
Behavior at the prompt
- Single-key hotkeys. The prompt reads one keystroke and dispatches
immediately — no Enter required. Bare Enter just redraws the menu.
Backspace, arrow keys, and Ctrl-C are silently swallowed. - Screen is cleared between menus so the new menu doesn't render
on top of the previous one. Q(logoff) confirms withY/Nso a stray keystroke doesn't
drop your session.
Display codes inside ansi_screen
The menu's ansi_screen content runs through the same Synchronet
@CODE@ and Mystic |XX substitution as standalone ANSI screens.
See doc 4 — ANSI screens for the supported code
table. Color pipe-codes (|07 etc.) are unaffected.