be487d7fd07d6496429a884cc862c287f773b22b
Picks up rubbs 6b32031, which renders GFM tables properly and makes the wiki/Files detail pane scroll with the mouse wheel. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Teletype BBS Server
Telnet-accessible Synchronet-style community BBS server built on the rubbs gem. Full-screen ANSI interface with a top menubar, stacked modal windows, message boards, multi-user chat, wiki integration, and a game catalog.
Running
Docker Compose:
docker compose up --build
Directly (Ruby 3.x):
bundle install
ruby bbs.rb
Connect:
telnet localhost 2323
Configuration
Copy env-example to .env:
| Variable | Default | Description |
|---|---|---|
BBS_PORT |
2323 |
TCP port to listen on |
BBS_SYSOPS |
empty | Comma-separated list of usernames with sysop access |
WEBAPP_WIKIJS_TOKEN |
— | Bearer token for the Wiki.js GraphQL API |
BOARDS_PATH |
data/boards |
Directory of per-board CSV files |
MESSAGES_PATH |
data/messages.dat |
Legacy single-board file; auto-migrated into the General board on first run |
LAST_CALLERS_PATH |
data/last_callers.csv |
Login log CSV |
PROFILE_PATH |
data/profiles.csv |
User profile CSV |
BBS_DESKTOP_ART |
data/art |
Path to a single ANSI art file (.ans, .ansi, .asc, .nfo, .txt) or a directory containing them — a random one is shown per session. CP437 / SAUCE-aware |
Interface
Connect, type a name at the prompt, then a full-screen Synchronet-style shell opens.
Keys
| Key | Action |
|---|---|
Alt+letter |
Open the matching top menu |
F10 |
Open the leftmost menu |
Tab / Shift-Tab |
Move focus inside a window |
Enter |
Activate the focused button / submit input |
Esc |
Close the top window / menu |
F1 |
Help |
F2 |
Message Boards |
F3 |
Quick post |
F4 |
Chat |
Menus
| Menu | Items |
|---|---|
| File | Bulletin · System Info · Exit |
| Messages | Boards… · New Post… |
| Files | Blog Posts · HowTo Guides · Game Catalog |
| Users | Online · Last Callers · Profile… |
| Chat | Open chat |
| Sysop | Console (sysops only) |
| Help | About · Keys |
Features
- Multi-board messaging — separate sub-boards (General / Tech / Off-Topic / Sysop), each in its own CSV file under
data/boards/. - Multi-line composer —
TextAreawidget, up to 1000 chars per post. - Live chat — broadcast hub, 1 Hz polling, history replay on join.
- Wiki split-view — list of titles on the left, selected page rendered on the right.
- Game card — selected game's story + external links.
- Last callers + online users + bulletin on login (last callers, message count).
- Persistent user profile — signature / location / homepage / notes per username.
- Sysop console — stats + broadcast (only for users in
BBS_SYSOPS). - xterm mouse — click menus, buttons, list items; wheel-scroll lists.
- Idle disconnect at 10 minutes.
- Configurable desktop art — drop
.ans/.ansi/.asc/.nfo/.txtfiles intodata/art/(or whereverBBS_DESKTOP_ARTpoints). Classic CP437 BBS art is auto-decoded; SAUCE metadata is stripped. With a directory, a different file is shown per session.
Project structure
bbs.rb entry point — services + Application
lib/
repository/
online_users_repository.rb thread-safe connected-user map
board_repository.rb multi-board CSV store
wiki_repository.rb Wiki.js GraphQL client
catalog_repository.rb games API client
last_callers_repository.rb login log
profile_repository.rb per-user persistent profile
service/
online_service.rb, board_service.rb, wiki_service.rb,
games_service.rb, chat_service.rb, last_callers_service.rb,
profile_service.rb
model/ value objects (MessageModel, GameModel, …)
ui/windows/ per-window builders (messages, wiki,
games, users, chat, bulletin, profile,
sysop, system info)
data/
boards/<id>.csv per-board messages (auto-created)
last_callers.csv login log
profiles.csv persistent user profiles
Data
All persisted state lives under data/ which is mounted as a volume in Docker
so it survives container restarts.
Description
Languages
Ruby
98.9%
Dockerfile
0.9%
Shell
0.2%