Viewing revision r1 of Development — saved 2026-08-03 01:34 EDT .
“Initial seed content”
Jump to current version Full history

Developing for ANetBBS

Want to write a door, a web feature, a theme, or hook into messaging?
You're in the right place.

The ten door types

ANetBBS runs door games via ten distinct backends:

  1. DOS doors (DOSBox-staging) — TradeWars, LORD-DOS, Usurper
  2. DOS doors (dosemu2, virtual COM1, no FOSSIL) — an alternative to
    DOSBox-staging for DOS games that need it specifically
  3. Native Linux doors — any executable, stdio piped
  4. Synchronet .js doors — real jsexec if installed, otherwise
    our built-in Node + Synchronet API shim (~270 functions)
  5. Mystic Pascal .mps/.mpx — bundled Mystic 1.12 A48 runtime
  6. Mystic Python .py — fake mystic_bbs module
  7. rlogin out-dial — DoorParty / A-Net Online / Synchronet xtrn
  8. Telnet out-dial — TWGS and other telnet-only remotes, no
    pre-auth handshake
  9. Built-in web games — Flask-routed mini-games
  10. In-browser DOS games — EmulatorJS + dosbox_pure, runs entirely
    client-side, no telnet/SSH client needed

See docs/17-development.md for the
deep-dive: drop file formats, token substitution table, working code
examples for each type.

Extending the web app

The web side is Flask + SQLAlchemy + SocketIO. Adding a new
feature is roughly:

  1. Create a blueprint in anetbbs/web/myfeature.py
  2. Register it in anetbbs/web_app.py
  3. Add templates in anetbbs/templates/myfeature/
  4. (Optional) Add a nav-bar link in templates/base.html
  5. (Optional) Add a model class (or a new column on an existing one)
    to anetbbs/models.py — see Database below, no migration
    command needed for the common case

The whole pipeline is ~50 lines of code for a working feature blueprint.

Database

anetbbs/models.py is the single source of truth for SQLAlchemy
models. There's no alembic/flask db migrate step in normal use —
web_app.py runs an auto-sweep (_lightweight_migrate()) on every
startup: it walks db.metadata.sorted_tables, and for any column a
model declares that the live table is missing, issues a permissive
ALTER TABLE ADD COLUMN (nullable, no default, so it always succeeds
on SQLite). Add a column, restart anetbbs-web, done. See
Architecture for the same mechanism described from the ops side.
A hand-written migration is still the right call for anything
destructive (renaming/dropping a column, backfilling data) — the
auto-sweep only ever adds.

Themes

Themes are DB rows with CSS variable values, edited visually at
/admin/theme-builder/. Add a new built-in theme by tweaking colors
in the builder, then add the resulting values to the default-theme
seed block in _create_default_data() in anetbbs/web_app.py
(there's no separate seed_data.py — it's all in web_app.py).

Real-time features

Flask-SocketIO is wired up in web_app.py. The Web Terminal and MRC
client are both reference implementations of a feature that spawns a
background eventlet greenthread, pumps bytes between a backend socket
and the browser, and handles reconnect.

Echomail / FidoNet networks

Pollers live in anetbbs/echomail/{binkp,qwk,tic}.py. Adding a new
network type is one new module + one new EchomailNetwork.protocol
discriminator.

Where to ask questions

If you ship something cool, PR it back and we'll bundle it with the
next alpha.

Reference

The authoritative deep-dive is at docs/17-development.md.
This wiki page is the lightweight community-editable companion.