#Welcome
ATDT is a complete bulletin board system that runs on ordinary shared web hosting. Callers get an authentic CP437 terminal in the browser: ANSI art, hotkey menus, message bases, file areas, live chat, and door games. You get a modern web console to run all of it.
Everything lives in one folder. The board is the atdt/ directory you uploaded;
all of its data (database, configuration, custom themes, door saves) lives in
data/ inside it. There is no daemon, no build step, and nothing to install on the
server beyond PHP itself.
Vocabulary
| Caller | A user of the board, connected through the terminal page. |
| SysOp | You. System operator: level 255, console access. |
| Node | One live connection. Two browser tabs are two nodes. |
| The matrix | The pre-login screen where callers log in or apply. |
| Area | One message base: a board within the board. |
| Category | A named shelf that groups areas in the area list. |
| File area | A shelf of files callers can download from, and upload to when you let them. They sit on categories of their own. New in 1.8.0; see chapter 23. |
| Door | A game or utility that runs inside the board. |
| ACS | Access Control String: who may see or do a thing. |
| Pipe codes | Inline color codes like |12 that color text. |
| Scope | A menu's own current message area, separate from the board's. Menus that declare the same scope name share one; menus that declare none use the board's current area, as ever. New in 1.6.5. |
| Console | The web admin at /admin/. Callers never see it. |
#Installing the board
Requirements
The installer checks all of this on its first screen and explains anything missing. On a too-old PHP it shows a friendly page instead of an error.
The install wizard
- Upload the contents of the
atdt/folder to your web space. The web root and a subdirectory (for example/bbs/) both work. - Visit
https://your-site.example/install.php. The environment check runs; continue. - Pick the database. SQLite needs nothing and is right for almost everyone; the database file
gets a randomized name inside
data/. MySQL asks for host, port, database name, user and password, with a test-connection button. - Board identity: board name (up to 60 characters), SysOp handle (3 to 20 characters: letters, digits, space, period, underscore, hyphen), SysOp password (minimum 8 characters, typed twice), board timezone (US zones listed first; this is the clock callers see and the boundary for the daily tick), and base URL (auto-detected; correct it if your board's public address differs).
- Done. The installer prints your cron line (chapter 17) and links to the board and the console.
install.php if you like, but you do
not have to. It locks itself and refuses to run while data/config.php
exists.Reinstalling
To wipe and start over, delete data/config.php (or the whole data/
folder) and visit install.php again. To upgrade in place instead, see
chapter 19.
#Your first hour as SysOp
The console lives at /admin/. Log in with the SysOp handle and password from the
wizard. Only level 255 accounts may enter; wrong passwords are throttled (five tries per 15
minutes, lockouts logged); every session rides a CSRF-protected cookie.
A sensible first hour:
- Open the board in another tab and look around as a caller. The seeded board has two message areas on a "Main Boards" shelf, a Files shelf with one General file area, a welcome bulletin, and two doors.
- Settings: confirm board name, timezone, base URL. Pick your new-user policy.
- Community: rewrite the welcome bulletin in your own voice.
- Areas: rename the starter areas or build your own layout with categories.
- File Areas: rename the General area, or drop a few files in its folder by FTP and scan them in (chapter 23.2).
- Themes / Editor: draw or import a logon screen.
- Leave the first oneliner. Boards feel alive when the walls have writing on them.
#What callers see
The terminal page is an 80 by 25 CP437 screen rendered with a real IBM VGA font. Menus respond to single hotkeys, prompts take a line of input, and a full-screen editor opens for message writing.
The clipboard works the terminal way: paste (Ctrl+V, Cmd+V, or the context menu) types into whatever accepts typing, a prompt line or the message editor, where pasted newlines become real line breaks. Drag-selecting any rectangle of the screen copies its text at mouse release, PuTTY style.
Keys echo (1.7.4). Press a hotkey and the character you typed prints at the cursor for the beat it takes the board to answer, the way a real terminal felt. The next screen paints over it, and a guard at the last column keeps a stray echo from ever scrolling the screen.
The cursor (1.7.3). The terminal keeps a classic blinking underscore at the resting position of every hotkey prompt: menus, pause lines, pagers, the whole logon tour. Before this, outside a typed-input field the prompts had no cursor at all, and a main menu only showed one where the board's own art happened to paint a blinking cell. It is drawn over the screen and never written into it, so art under the cursor survives untouched; typed fields keep the caret they already had, and a dead line shows nothing, as it should.
The matrix and new users
Before login: L to log in, A to apply, G to log off. Applications ask for handle, password, location, your custom question, and an optional email address; ENTER skips it. What happens next follows your new-user policy: approve (waits for you; the dashboard shows pending), auto (activates instantly), closed (no applications).
With outgoing mail configured (chapter 6), the matrix also answers R for a forgotten password. Since 1.6.0 it takes one press: right after a failed login, R sends the reset for the handle just tried, with no retyping. Pressed cold, it opens a small PASSWORD RESET screen asking "Reset for:" instead of bouncing back to the login line. Either way, if the account has an email on file, a single-use reset link (20-minute clock) goes out. The matrix answers the same sentence whether or not the account exists, one link per 15 minutes per account, and SysOp-level accounts are excluded on purpose (a SysOp handle is told so in as many words, so nobody waits on a letter that will never come). With mail off, R is not a key.
Nobody can park at the matrix, either: the idle hang-up (chapter 6) applies before login the same as after, so an abandoned tab stops holding a node.
The post-login sequence
The order is yours as of 1.7.3. Settings grew The logon tour: give each stop a position or turn it off, and the board walks your arrangement. Turn everything off and a caller lands straight at MAIN. Stops with nothing to say still skip themselves, as before, and two courtesies keep their seats whatever you arrange: the one-time email ask for an account with no address on file, and the mail check when letters are waiting. A board that never touches the setting runs the classic order below, unchanged.
Connect banner (optional modem ceremony; since 1.6.0 the CONNECT number matches the board's Line speed, CONNECT 9600 out of the box or CONNECT 28800 with the throttle off), logon art, a one-line email ask for accounts without one (ENTER skips), every unread bulletin oldest-first (a brand-new caller walks the whole history once; edits do not re-greet), the auto-message wall, a random rumor, mail check, last callers, then the MAIN menu. Any key advances.
The default menu map
| Key | Where |
|---|---|
| M | Message menu. Read, post, new scan, change area, mailbox. |
| F | File areas. List, new files, search, upload, change area. New in 1.8.0; on an upgraded board F, or the first free digit (chapter 23). |
| C | Chat. The live room, everyone together. |
| D | Door games. HILO and Star Merchant. |
| I | Info desk. BBS list, board stats, bulletins. |
| P | People. User list, last callers, who's online. |
| O | Oneliners. The graffiti wall. |
| B | Bulletins. SysOp announcements. |
| Y | Your settings. Bell, connection speed, password. |
| G | Goodbye. Log off, with confirmation. |
Every menu, item and hotkey is editable in the menu designer.
Caller-side settings
Each caller gets a terminal bell toggle, a nostalgic connection-speed throttle (300, 1200, 2400, 9600 or 14400 baud, or off; keypresses drain the buffer instantly), a password change, and an [E]mail row to set, change or clear the address on their account. The mail room also answers S to flip between the inbox and the letters they have sent.
Two 1.6.0 notes on the throttle: new accounts start at the board's Line speed (chapter 6) instead of a hard-coded number, and the typing-out now genuinely covers everything. Changing message areas and the goodbye screen used to paint instantly; both now reveal at the wire speed like the rest of the board, and the line waits for the farewell to finish before dropping carrier.
Threads fold (1.7.9). In the message list, - folds the replies under the
highlighted message away, and from a reply it folds the whole thread that reply belongs to,
moving the bar to the top of it. + opens them again, * folds or opens every
thread at once, and T jumps the bar to the message this one answers. A folded row ends
with what it is hiding, [+12, 3 new], in yellow when any of it is unread. Folding
lasts the call; a fresh call opens everything.
The tree says which messages have replies: a triangle pointing down when the replies are on show, right when they are folded away, in the gutter before the subject for a thread root and on the branch for a reply. A message with no replies draws a plain line. Past the fourth level the tree steps in one column a level, a staircase, until it meets the subject column, so a chain of twelve replies still reads as a chain.
The columns, as of 1.7.9: From takes 20 characters, the longest a handle can be, so nobody is clipped; the message number takes five digits, which a big import reaches; the subject gives up a little room for both, and the header sits over the columns.
Read marks are honest (1.6.1): because lists run newest-first, a caller often opens a fresh reply before an older message they have not seen. The read pointer used to leap over the older one and mark it read on the way past. Now each message is marked read when it is actually on the screen, the unread markers and the new-scan keep pointing at whatever was skipped, and the pointer catches up by itself once the gap is walked. Reading feels the same; the ledger simply stopped rounding up.
The message list (1.6.0): threads sort by their date, newest first, with replies always nested beneath their thread. Because the sort reads the date, a timestamp fixed from the console re-files the thread automatically. S in the list flips to oldest-first and the choice sticks to the account; unread messages are caught either way by the new-scan. List dates show the year. New in 1.7.0: Home and End jump to the top and the bottom of the list, and the command line under the list says so. Sorting keeps your place, and one press of Home puts you back at the top.
The area list, rebuilt in 1.7.6. Each board's description sits on its own line right under the board's name, in cyan, instead of on a gray row under the prompt. A board without a description takes one line, as before, so a list that never filled them in looks as it did.
The highlighted board is a white-on-blue lightbar with its number in yellow. On the other rows the numbers are cyan, the tags green, the names bright while the board holds unread messages, the message counts cyan, and the unread count yellow when there is one. The scrolling window keeps a board and its description together: arrows, PgUp, PgDn and the "more above" and "more below" rails all count in whole boards, and the window grew from thirteen rows to fifteen to make room.
Long letters page (1.7.0). The mail room used to cut a letter off at the bottom of the screen; it now pages with N and P and a page indicator.
Help is a menu (1.8.0). The caller's help used to be two fixed pages. It is a menu now, with a page each for colors, the board, message areas, file areas and the keys, and a HELP item on any menu can open one page directly (chapter 10).
A bar over the door (1.8.0). While a caller is in a door, a slim strip above the terminal says where they are: the board, the door, the node, the minutes left and how many are playing. Buttons on it explain the keys and get the caller out (chapter 15).
#The Dashboard
The console home page. Everything urgent surfaces here.
- Stat cards: calls today and ever; messages today (public posts only: since 1.8.0 a private letter does not count); pending callers (with inline approve when your policy is approve); cron health in minutes since the last tick (a dash means it never ran).
- Who is online: every live node with handle, activity and idle time, plus three buttons per caller. Join chat drops you into the public room; Break in opens a private line to that caller (chapter 14); Log off (new in 1.6.0) hangs up that line. The caller sees "The SysOp has closed this line." and NO CARRIER, the node frees immediately, and the action lands in the admin log. It asks before it fires, and the line leaves the list the moment you confirm.
- The chat panel mirrors the room without you holding a node. The target selector aims your words: everyone in the public chat room, or a private line to one node. A banner above the box always shows where the next line goes, and a caller's page arrives with the form pre-aimed.
- Broadcast: type a message, pick minutes, and every connected caller sees it as a banner above their screen, whatever they are doing. Separate from chat; never lands in room history.
- One-time notices: after an upgrade, a card says what changed and goes away for good once you dismiss it. Theme string changes arrive this way (chapter 11). On 1.8.0 a card also says which key File Areas took on MAIN, or that no key was free and the item is waiting, hidden, for you to give it one.
#Settings, every field
Identity
| Board name | Terminal title, banners, %BN in theme strings. |
| Base URL | Public address; used in generated links and cron advice. |
| Board number | What the connect ceremony dials; also %PH in theme
strings. Blank keeps the classic number derived from the board name. |
| Board timezone | The clock callers see everywhere; the daily-tick boundary. Storage stays UTC. |
Access
| Max nodes | Simultaneous callers (default 10). Past the cap: a busy screen, like a full modem bank. |
| New user policy | approve / auto / closed. |
| New user question | Your custom application question; answers land in the caller's note field. |
| BBS list additions | ACS for who may add directory entries (blank = everyone,
v = validated). Viewing is always open. |
| Banned addresses | One per line: an exact IP, a prefix ending in *
(203.0.113.*), or a # comment. A banned caller gets the
connect.banned theme string instead of a dial tone, before any session exists. A
ban landing mid-call drops the line on the next keystroke. |
| DOS doors | New in 1.7.0. The master switch for running original DOS door games (chapter 21). Off by default, and off means no console page, no menu action, and an API that answers 404: callers cannot tell the feature exists. |
| Board offline | New in 1.7.0. For maintenance days. Nobody can connect or log in, not even a SysOp account, until it flips back. New callers get a notice in your own words (pipe colors welcome; a stock line covers a blank box) and then the line drops. Callers already on stay on; a separate Disconnect everyone now button hangs up every line at once when the work needs the board empty. Every console page shows a reminder while the switch is on. |
| Prohibited words | New in 1.6.1. One word per line;
sysop ships on the list. A new application's handle is refused if it contains
any listed word anywhere, in any case: put test on the list and Test, Testicle
and Youtestit are all turned away. Nothing is retroactive, since the list is read only when a
new handle is typed, so existing accounts keep their names. |
Three prohibited names in a row ends the application: the board shows the caller the address
they are calling from, notes it in the security log, and drops the line. Any clean attempt in
between, even a malformed or already-taken one, resets the count. The refusal and the goodbye
are theme strings like everything else (nua.banned_handle,
nua.banned_bye, nua.banned_ip), so a themed board words its own
bouncer.
Display
| iCE colors | Bright backgrounds instead of blinking text. On if your art uses them. |
| Connect ceremony | The fake modem handshake on connect. Pure theater. |
| Allow user color | Callers may color their text with pipe codes in messages, mail, chat, oneliners, rumors and the auto-message. Off shows codes as typed. |
| Default theme | The theme every caller sees unless a specific one is set on their account (Users page). The everyday flow: duplicate default on the Themes page, edit the copy, pick it here. |
| Message list on arrival | New in 1.7.9. Open, every reply on show, which is the default and how the board has always behaved; or Folded, one row a thread with a tail saying how many replies wait and how many are new, the bar landing on the thread hiding the oldest unread. Callers fold and open with the same keys either way, and their choice lasts the call. |
| The logon tour | New in 1.7.3. The order of the cards between the password and the main menu: welcome screen, unread bulletins, auto-message, rumor, last 10 callers. Give each stop a position or turn it off. Everything off means a caller lands straight at MAIN. The email ask and the mail check always keep their seats. |
| Line speed | New in 1.6.0. The board's default baud: 300, 1200, 2400, 9600, 14400, or "No throttle (CONNECT 28800)". New callers start here, the pre-login screen always types out at it, and the CONNECT banner shows the matching number. Default 9600. 14400 (added in 1.7.8) is the fastest speed that still types itself out; above it a screen arrives whole. Dropping below 9600 is charming to modem veterans and can read as broken to everyone else; the save reminds you. |
| Idle hang-up | New in 1.6.0. Minutes of caller silence before the board hangs up the line and frees the node, measured on keypresses rather than the browser's background polling, so an abandoned open tab cannot hold a node. Applies at every screen, the matrix included. Default 30; 0 disables. |
| SysOp chat style | New in 1.6.0. How break-ins and answered pages look on the caller's side: classic (one shared scroll) or split (the caller types in the top pane, your words fill the bottom, a labeled rule divides them). Default classic; the console side is the same either way. |
Outgoing mail
Send-only email through a mailbox you own. The board never reads a mailbox, and with the switch off (the default) it sends no mail and opens no mail connection of any kind.
| Outgoing mail | The master switch. Off hides every mail feature on the board. |
| Transport | smtp (host, port, STARTTLS or SSL, username, password)
or the hosting company's PHP mail(). |
| From address | What the letters are sent as; usually the mailbox you configured. |
| Send test | Proves the setup in one click; the result lands in the events log. |
What it unlocks: password resets from the matrix (R), the EMAILSYSOP menu action (callers write you a letter; replies go to their own email via Reply-To, one per caller per day), and the email question at application and logon. Every send lands in the events log. Caller emails are never verified, never shown to other callers, and visible only in the Users drawer.
SysOp notifications
New in 1.6.1, and strictly opt-in in the same way outgoing mail is: with no browser enabled, the board makes no outside connection for this at all. Enable it on a browser, desktop or phone, and a caller's page arrives as a real system push notification naming who is calling, which node, and the reason they gave, whether or not the console is open anywhere. Tapping it opens the console on their line, ready to answer.
- Standard Web Push, nothing borrowed. The board mints its own VAPID keys on first use and talks straight to the browser's push service. No libraries, no third-party account, no other party's JavaScript on your console.
- Enable as many browsers as you like, remove any of them from the same card, and send yourself a test ring to hear what a page feels like.
- Never in a caller's way. Pushes go out best-effort with short timeouts, so a push service having a bad day cannot slow the caller whose page is ringing. Dead subscriptions prune themselves.
File areas
New in 1.8.0. The card holds the largest upload (10 MB to start), the minimum
description length, whether to read FILE_ID.DIZ out of uploaded zips, whether to
show who uploaded a file, the daily download limit, and how long a download link lives. Below
those sit the two economies: an upload-to-download ratio with its grace, and file points with
their rates. Every economy ships off. Each field, with its default and its range, is in
chapter 23.3.
Release check
New in 1.7.8, and on by default. Once a day the board reads one small text file from the ATDT website to learn what the current release is, and the console's version lamp says where this board stands: green when current, amber when a newer release is out, red when a whole major version has gone by, grey when the check has not run, could not run, or is switched off. When there is something to fetch, the Dashboard carries a line naming the new version with a download link.
- It carries nothing about your board. The request is a plain ask for a file: no board name, no address, no version, nothing in the query string.
- It never slows the console. The nightly housekeeping does the checking, or the pseudo-cron riding the tail of a caller's request, on a three-second leash at most. The console only reads what was stored; nothing reaches out on a page load.
- A host with no outbound network leaves the lamp grey, says so once in the log, and carries on.
The section shows the time of the last look, what it found, and a Check now button. Turn it off and the board never reaches out; it then behaves exactly as 1.7.7 did.
This console
Settings that belong to you rather than to the board. Callers never see any of it.
| Console theme | New in 1.7.9. Dark, the console as shipped; Light, a light work surface under the same dark instrument rail; or Follow the browser, which takes the browser's own preference and changes with it. The login page wears your choice too. Dark stays the default. |
| Center the console | New in 1.7.8. Off by default. Centers the console, rail and all, once the window is wider than the console needs, because on a very wide screen a maximized browser otherwise leaves the whole thing against the left edge. It changes nothing about the pages themselves, only where the machine sits on the desk. |
Advanced
Call log keep window, new in 1.7.9: how long a row stays in the call log before the prune tool (chapter 19) takes it. A year unless you change it; 0 keeps every call forever.
The cron key
The Settings page shows the exact cron line for cPanel and a button to mint a new key. A new key invalidates the old one immediately; update your cron entry to match.
#Users and access
The list
Search by handle, filter by status, sort by any column; capped at 200 rows (narrow the search past that). Pending applications float up with one-click approve.
The edit drawer, field by field
| Level | 0 to 255. New callers start at 10; 255 is SysOp (console access, passes every ACS). |
| Flags | Twenty-six checkboxes, A to Z. Meaning is yours; ACS tests them with
fA and so on. |
| Status | active / pending / locked / deleted (soft; the row stays). |
| Location | Free text, shown in the user list and last callers. |
| Note | Private SysOp note; application answers land here. |
| The address password resets go to. Optional, never verified, never shown to callers; only you see it. | |
| Theme | Which theme this caller sees. |
| Last call | New in 1.7.0. Set a caller's last call date on the board clock, or clear it to never. For the SysOp bringing in decades of history whose callers should not all read as if they never called. |
| Files | New in 1.8.0. The caller's uploads and downloads, beside their calls and posts. While file points are on, the balance shows too, and you can set it. |
| New password | Type once to reset; blank leaves it alone. |
The level ladder: 10 = fresh caller; 20 and up = yours to define; 100 = a handy
co-SysOp line (s100); 255 = SysOp.
#Access strings (ACS)
One tiny grammar controls visibility everywhere: message and file areas (read and write separately), menu items, bulletins, voting questions, doors, menu backdrops. Blank always means everyone. Level 255 passes everything.
| Token | Passes when |
|---|---|
| s50 | Level 50 or higher. |
| fA | Caller has flag A. |
| v | Account is validated (active). |
| !fZ | NOT: caller lacks flag Z. |
| s50fB | Side by side = AND. |
| s50|fB | Pipe = OR. |
| (s50|fB)!fZ | Parentheses group. |
Recipes: v members only · s100 co-SysOps ·
fP flag-holders · s255 you alone.
A worked example
Access strings are easier to understand as a set than one at a time. Suppose fresh callers stay
at level 10, trusted regulars get bumped to 50, your co-SysOp sits at 100, and flag
P goes to anyone allowed in the private lounge.
Notice what each choice buys you. A blank read ACS means the area shows for everyone including
a pending application, which is usually right for a general board and never right for a private
one. Write s255 makes a read-only announcements area without a separate feature
for it. And because a failing caller never sees the line at all, the Lounge simply does not
exist for anyone without flag P: there is nothing to ask you about.
#Message areas and categories
Areas are the message bases. Categories are named shelves that group them: callers see each category as a header with its areas beneath, and the reader labels the area "Category / Area."
Categories
- Add (name up to 30 characters), rename inline, reorder with arrows. The caller list follows this order exactly.
- Delete: the category goes; its areas stay, loose. Nothing else is touched.
- Areas without a category gather under "Other Boards" at the end. A board with no categories shows the plain flat list.
Areas, field by field
| Tag | Short unique key, 2 to 12 characters (A to Z, digits, underscore), unique board-wide. |
| Name | Display name, up to 40 characters. |
| Description | One line under the name, up to 100 characters. |
| Category | The shelf it lists under, or none. |
| Read ACS | Who sees the area at all. |
| Write ACS | Who may post. Read-only announcements: write ACS
s255. |
| Listed | New in 1.6.5. Checked by default. Unchecked, the area leaves the general area-change list and nothing else. See below. |
- Arrows reorder an area within its own category (the order callers see).
- Delete refuses while the area holds messages; empty it first.
- The private mail spool is plumbing; the console will not let you edit or delete it.
Listed and unlisted areas
Every area has a Listed checkbox, checked by default. Uncheck it and the area disappears from the general area-change list, and from nowhere else. That is the flag's entire job.
An unlisted area still:
- counts its messages everywhere totals appear;
- shows up in the global new scan for any caller who passes its Read ACS. A caller with access deserves to hear about mail waiting for them;
- opens normally from any menu item that names it (chapter 10.4), from a category-filtered area change, or as a menu's default area;
- keeps serving a caller who was already reading it when it went unlisted.
#Themes
A theme is the board's wardrobe: every caller-visible string, plus which art gallery pieces dress the three big moments. The default theme is the board's permanent fallback and is never editable: not its strings, not its art. To change anything, Duplicate it and edit the copy; anything missing in your copy falls back to the built-in look, so you can never break the board permanently.
- Duplicate: copy any theme into an editable one under
data/themes/<name>. - Strings: every caller-facing string, grouped, with a live pipe-code preview. Saves
write your
strings.inioverlay. - Art: three bindings, connect (the pre-login screen), logon (the welcome), goodbye (the farewell). Each picks a piece from the art gallery, or "(generated default)" for the board's own drawing. Live previews render through the real terminal parser.
- Connect art can be as tall as it likes (1.7.7). The board's login line used to paint across rows 20 to 24 whatever the art did, so a connect screen taller than nineteen rows lost its last rows underneath it. The line now sits two blank rows below wherever the art ends, so a 21-row screen keeps every row and the prompt lands at the bottom. Art up to seventeen rows, and the board's own generated banner, sit exactly where they always did.
- Delete: blocked for the board's current default theme and while any caller wears it; deleting a copy of a shipped theme lets the shipped version show through.
- Export (1.6.0): every theme row but default has an Export link that downloads the
whole look as one self-contained
<name>.atdt-theme.json: strings, metadata, art bindings, and the art bytes themselves. Made for trading. The default theme is not exportable on purpose, since every board already ships it; duplicate it and export your copy. - Import a theme (1.6.0): the card at the bottom of the Themes page takes such a file and installs everything in one step. A taken theme name is uniqued (-2, -3 and so on). The art lands in the gallery with byte-level care: a piece identical to one already on the shelf is shared rather than duplicated, and a name clash with different bytes is renamed with the theme's bindings remapped to follow. An import can never overwrite art you already have, and the flash message says exactly what landed, what was shared and what was renamed.
- Which theme callers get: the Default theme picker in Settings covers everyone at once. A specific caller can be given a different theme in their edit drawer on the Users page ("(board default)" means they follow the Settings choice). New accounts follow the board default.
The everyday loop: duplicate default, edit your copy, set it as the board default in Settings. Done; every caller sees it.
The lists so far. 1.5.0: the mail-room pair (
mail.pick,
mail.pick_empty) and the settings prompt (set.prompt).
1.6.0: the matrix reset strings (matrix.reset_ask reworded;
reset_note, reset_sent_for, reset_sysop new), the
split-chat labels (sysopchat.split_top, split_bottom), and the
message-list command bar (list.commands, which now offers S to flip the
thread order). 1.6.1: the three application-desk strings
(nua.banned_handle, nua.banned_bye, nua.banned_ip).
1.6.5: two new denial strings for targeted areas. 1.7.0:
list.commands (it now mentions Home and End), nua.bad_handle (handles
may carry [ and ] now, a small courtesy to the C64 crowd), and the new
mail.read_more for the paged mail reader. 1.7.9: list.columns
(the From column moved) and the new list.navkeys, split out of
list.commands. Until 1.8.0 the 1.7.9 card showed the 1.7.0 list by mistake, so a
board that dismissed it should look at those two. 1.8.0: two new sections,
[fareas] and [files], and a reworked [help], which is a
menu with pages now; help.more is gone.Goodbye art, one note (1.5.5): the farewell piece now always paints on a cleared screen
and +++ NO CARRIER prints on row 25, so even a full-height goodbye keeps every
row.
#The ANSI editor and the art gallery
A full drawing program at Console › Editor: an 80 by 25 CP437 canvas rendered by
the same engine callers see. Everything it saves lands in the art gallery, one
board-wide shelf of .ans pieces under data/art/, and everywhere the
board can wear art picks from that same shelf by name.
Live text in art: type an MCI code into a piece with the Text tool and it expands when the art is displayed. "WELCOME TO %BN, %HN" on a logon screen greets every caller by name (Appendix B lists the codes).
A bare code pushes the rest of its row along, so leave drawing room to the right of it. Put an
exclamation mark in front (!%VN) and the value stamps in from the mark rightward
instead, over whatever is already there, leaving the row exactly as wide as you drew it. Mark
the codes you put inside a box or a table so the frame keeps its right-hand border, and leave
the cells just right of the code clear; leave the codes in sentences bare.
New in 1.7.7, and a code left bare behaves as it always has.
Tools
| Pencil (P) | Stamp the current glyph in current colors. |
| Half-block (B) | Paint 80x50-feel pixels; right-drag erases. |
| Text (T) | Click and type. |
| Glyphs | The picker offers the classic CP437 sets. Since 1.7.9 it also offers the pictures below 0x20, the smileys, card suits, arrows and notes, and a saved file keeps them: they draw properly now in menus, bulletins, the gallery and doors, where they used to be dropped as control codes. |
| Font (O) | New in 1.5.5. Big ANSI letters, TheDraw style: pick a font, click, type. |
| Line (L) | Drag a straight run. |
| Rectangle (R) | Drag a border box. |
| Flood fill (F) | Fill a region. |
| Recolor (C) | New in 1.5.5. Repaint with the current ink; the characters stay put. |
| Select (S) | Drag, then Copy / Move / Tint / Blank. New in 1.5.5: Move and Copy lift the block visibly, steer with mouse or arrows (Shift moves by five), Enter or click places, Esc puts it back. |
- Palette: 16 foregrounds, 8 backgrounds (16 with iCE colors on).
- The glyph row holds the full CP437 set.
- Undo Ctrl+Z, redo Ctrl+Y; zoom and grid on the toolbar; Clear blanks the canvas (it asks first, and Undo brings it back).
- The canvas autosaves to your browser while you work.
Letter fonts
New in 1.5.5. The Font tool types words as large ANSI letters, the way TheDraw's
.TDF fonts did. Four fonts ship (Block, Block Wide, Block Shadow, Small), covering
A to Z and 0 to 9 and stamping in your current ink. Enter starts a new line,
Backspace steps back, and letters wrap like a typewriter.
Fonts... opens the font library, a small editor of its own: draw your own set glyph by
glyph (up to 16 wide by 8 tall, any colors, so your fonts stamp exactly as drawn), and it
appears in the Font picker alongside the shipped four. Stored as JSON under
data/fonts/; transparent cells leave whatever is under them alone.
The gallery
- Open: pick any piece off the shelf and edit it.
- Save to gallery: writes a real
.answith a SAUCE record under the name you give; anything bound to that name updates instantly. - Delete: takes a piece off the shelf; screens bound to it fall back to their generated look.
- Import: upload any
.ans(256 KB cap), including classic scene art with iCE backgrounds, then Save it to the gallery. - Export: download the exact bytes; PabloDraw and Moebius open them. Round trips are pixel-identical.
- The Gallery page (1.5.5): Console › Gallery shows every piece with a rendered preview, ten to a page, each with an Open-in-editor button. The dropdowns stay the fast path on a small shelf; this is the walk-the-aisles view for a big one.
Where pieces get used
| Connect / logon / goodbye | Themes page › Art: bind each slot to a piece. |
| Menu backdrop | Menus page: the Backdrop picker on the menu. |
| Per-level backdrops | Menus page: Backdrops by level (first ACS match wins). |
| ANSI bulletin | Community page: the art picker on the bulletin form. |
| ART menu item | The item's argument names the piece. |
#The community desk
One console page, six tabs, alphabetical on the rail; the page opens on Auto-message.
- Message boards (1.6.0): every category and board, listed the way a caller sees them, with live message counts. Open a board and every message is there, newest first, 25 to a page, with a one-click flip to oldest-first (the same date-driven order callers see, so a fixed timestamp re-files a message here too). You can edit the subject, the body, and the date and time stamp (entered in board time, stored UTC), and you can delete a message (soft, the same as caller-side deletes). Two things never change: who wrote it and where it sits in the reply tree. Those are facts of the record, shown read-only above the form. Private mail is a different matter entirely: mail areas are excluded from this tab at the query level. The console does not read anyone's letters.
- Bulletins: title (60 characters), body (pipe colors render; word-wrap at the full 80 columns), or an ANSI art slot shown full-screen instead. ACS per bulletin; sort orders the list; a fresh save greets every caller once at next logon. Anything updated since a caller's last visit is shown to them automatically; the key for browsing them at will is whatever your menu designer says it is.
- Oneliners / Rumors: callers write, you hold the eraser. One random rumor greets every logon; prune the duds.
- Voting booth: question (100 characters) plus 2 to 10 options and an optional ACS. One ballot per caller; bar-graph results. No editing once ballots exist: close (results only) or delete (ballots too).
- BBS list: the other-boards directory. Callers add (gated by the Settings ACS); you
edit and delete. Addresses must be
https://,telnet://, orhost:port. - Auto-message: one board-wide wall message shown at logon; callers who pass its ACS rewrite it from the caller side.
#Chat, break-in, paging and broadcast
- The room: one public channel, every node. History pages with PgUp and PgDn or the arrows; a half-typed line survives paging; timestamps show the board clock with dates across midnight. Long lines word-wrap onto up to three display rows instead of clipping at the right edge, so every typed character shows.
- Page SysOp: the caller pages with a reason; the console chat panel arrives pre-aimed at their node.
- Break in: from the dashboard, next to any caller. Opens the private line: the caller gets a bell and a banner naming you, and the private conversation interrupts whatever screen they are on (except mid-editor, where it politely waits so their draft survives, and lands the moment they finish). Everything on the private line is invisible to the room. ESC or Q returns the caller to what they were doing.
- The split screen (1.6.0): Settings offers a second style for the caller's side of a break-in or an answered page. In split, the caller keeps the top half of the screen for their own typing, your words fill the bottom half, and a dim rule with name tags divides the two: a proper old-style SysOp chat. Classic (one shared scroll) remains the default, the console side is identical either way, and the style is picked up fresh for each conversation.
- The room keeps its history (1.6.1): housekeeping used to sweep every chat line older than seven days, so a board with a slow week woke up to an empty room. The public room now keeps its newest 1,000 lines however old they are, and only the overflow past that cap is swept. Transient wire traffic (page requests, private SysOp lines and their hang-up markers) still expires after a week, as it should.
- Tidy the room (1.6.5): every public chat line on the console's live wire carries a delete link. One click and a confirm removes that line from the room for good, with an audit line in the admin log recording who said what. Pages and private SysOp traffic are working records; the link never appears on them, and the guard refuses them outright.
- Broadcast: a timed banner above every caller's screen for the minutes you choose. Never enters chat history.
#Door games in the console
The registry
Every door is one folder, and door folders live in the doors/ directory of your
ATDT installation, alongside the shipped games. If your board is at
www.example.com/atdt, a door called Dice Run is atdt/doors/dicerun/.
Scan reads that directory and registers what it finds.
Registering is all Scan does: no menu changes. To put a door in front of callers, use the Menus page like for anything else: add an item with the DOOR action, and every registered door is offered in the item's argument list automatically. Door entries are ordinary menu items: rename, re-key, reorder, hide or move them at will (the shipped DOORS menu's HILO and Star Merchant rows are just such items).
Per door here: enable or disable, display title, ACS, sort. A disabled door keeps any menu items but refuses to open; delete the item in Menus if you want it gone from the list too. A door whose folder went missing is flagged for re-upload or removal.
The door bar
New in 1.8.0, and it needs nothing from you. While a caller is in a door, a slim strip above the terminal shows the board, the door's title, the node, the minutes left and how many callers are in the door. The terminal moves down to make room.
The bar has buttons. Keys opens a short card on what the keys do and how to get out. Full screen does what it says. In a DOS door, Leave door first mentions the game's own quit, then sends three Ctrl+] the old way. A DOS door can also put its own status line in the bar, a switch on its page (chapter 21.5).
HILO
The number-guessing classic; no settings; its scoreboard feeds the Stats screen. Its source doubles as the SDK example.
Star Merchant
An original space-trading game in a persistent galaxy that generates itself the first time anyone opens the door. First-time players land on a two-page in-game primer; ? or H reopens it anywhere.
| Sectors | Galaxy size for the NEXT generation (takes effect on reset). Default 1000. |
| Turns per day | Daily action budget (default 250); the day-tick refills. |
| Combat | Master switch; off = purely economic galaxy. |
| Reset universe | Regenerates everything and erases every player. Type RESET to confirm. |
| Top merchants | The net-worth ladder. |
| Game log | Conquests, bounties, weekly ladder closes. |
What the day-tick does: port stocks drift 15 percent toward full; colonized planets produce by class; banks earn 0.5 percent; turns refill; fresh derelicts scatter; pirate crews drift one warp and respawn toward one per 50 sectors (never into Charter Space, sectors 1 to 9); weekly, the ladder snapshots into the hall of fame.
#The Door API
A door is one folder with a manifest and a PHP class. The board provides screen, input, storage and identity; the door returns frames. Nothing a door does can take the board down.
#Cron and the daily tick
The cron endpoint runs housekeeping. With a real cron entry it fires every five minutes; without one, pseudo-cron performs the same work piggybacked on caller traffic (it kicks in when the last tick is older than 15 minutes, guarded by a lock so only one request does it). Either way:
- Every tick: sweep dead sessions (nodes free up); prune events older than 90 days, and transient chat traffic older than 7 days. The public room keeps its newest 1,000 lines regardless of age (chapter 14).
- At board midnight (your timezone): each enabled door's
cron.php, thendata/logsrotation.
The cPanel line, printed by the installer and the Settings page:
The key guards the endpoint (cron.php?key=... over HTTP works too); wrong keys are
refused and logged. The dashboard card shows minutes since the last tick.
#Logs and events
| Events log | Everything notable, with a level. security covers login
lockouts on both surfaces; cron records ticks and failures; perf appears if a
response ever exceeds the 64 KB budget; door lines arrive tagged
door:<slug>. Hang-ups land here too (1.6.0): a console Log off and an idle
timeout each leave one line naming the node. Since 1.6.1, an applicant dropped for three
prohibited handles in a row leaves a security line naming their address. |
| Admin log | Every console action with who did it, so a co-SysOp's work is auditable. |
| Call log | One row per call with duration and a summary ("Posted 2 msgs, played HILO"). Since 1.8.0 a private letter is not a post, here or anywhere else. |
#Backups, upgrades and recovery
Backups, from the console
New in 1.7.9. Database, under The machine, has a Backup tab that puts the whole
board in one zip: data/ (art, themes, door saves, config) and the database,
whichever engine you run. On SQLite that is a consistent snapshot rather than a copy of the live
file; on MySQL it is a dump the board writes itself, one statement a line, so nothing on the
host is needed. A manifest inside vouches for every entry with a hash.
| Where it goes | A server path you name. The board refuses a path inside the web
root or inside the board itself, because a zip holding the database and your credentials under
public_html is a breach waiting to happen. Or data/backups, which the
web cannot read, for a download through the console. |
| How many are kept | The newest few; older ones are removed. You set the number. |
| On a schedule | The scheduled backup sits beside the maintenance tools with the same every-N-days setting, and writes to the server path. |
| Include file areas | New in 1.8.0. A checkbox. The tab shows what the
backup weighs with the files and without them, and warns past half a gigabyte; a restore puts
the files back. Only the stock folders under data/files go in. A file area kept
in a folder of your own outside the board is yours to back up. |
Restoring
From an upload, or from a backup already on the server. The board reads the manifest first and refuses a backup made on the other database engine, by a newer ATDT than this one, or changed since it was made. Then, in order:
- the board goes offline;
- a safety copy of the board as it is now is written into
data/backups; - the files and every table are replaced;
- the schema is brought up to this release from whatever version the backup carried;
- every session ends;
- the board is left offline, for you to look at before switching it back on.
config.php is never overwritten. This host's address
and database credentials stay exactly as they are, and the backup's copy is left beside it so
you can compare. Typing RESTORE confirms the whole thing.What a backup holds, by hand
If you would rather do it yourself: everything that is yours lives in data/, which
is configuration, the database on SQLite, theme overlays, the art gallery, your letter fonts,
door storage and the files in your file areas. Back up that one folder and you have the board
(on MySQL, dump the database too). Two things can sit outside it. A door you installed yourself
is code in doors/, so keep its zip or fold that folder into the backup as well.
And a file area pointed at a folder of your own keeps its files there.
The database toolkit
New in 1.7.9. The Database page lists what the board can do for itself, each with a Run now button and an every-N-days setting the nightly housekeeping honors. A status card above them shows the engine and its version, the size, what a vacuum or optimize would give back, the file and its journal on SQLite, and the largest table on MySQL.
| On SQLite | Quick and full integrity checks, optimize, analyze, a write-ahead log checkpoint, and vacuum. |
| On MySQL | Check, analyze and optimize tables. |
| On both | Purge deleted messages (until now a deleted message stayed in the table, invisible). Purge deleted callers: they used to stay in the list after deletion; now they go, with their read pointers, while their messages stay under their name. Prune the call log to the keep window set under Settings. Sweep orphaned rows. And a schema doctor that compares the live tables to what this release expects and adds anything missing. |
cron.php called by cron or wget, never from the pseudo-cron that
rides a caller's request under the host's time limit. A heavy tool that had to wait says so on
the page, and the Database entry in the rail shows a count when something failed or is
waiting.Upgrading in place
- Upload the new release's files over the old ones. The zip contains no
data/, so an overwrite upload cannot touch your data. - The first page hit migrates the database automatically if needed.
install.phpcoming back with the upload is harmless; it self-locks.
Since 1.7.9, take a backup first. The Backup tab makes that a one-click job, and a restore puts the board back if an upgrade goes somewhere you did not want.
Skipping versions is fine. The migration is a single ladder keyed on the stored schema version: a board that missed a release (or five) climbs every rung it lacks, in order, on that same first hit. There is nothing to run by hand and no intermediate build to install; upgrading 1.0.0 to any future version is always the same overlay upload. The ladder runs under a lock so two simultaneous first-hits cannot collide, and the 1.1.0 rungs are safe to re-run if a crash interrupts them.
Recovering a lost SysOp password
With another level 255 account: reset it from the Users page. Without one: any database tool
(or a one-visit PHP snippet you delete after) setting users.pass_hash to the output
of PHP's password_hash() for your new password.
Troubleshooting
| Symptom | Cause and fix |
|---|---|
| Board looks broken after upgrade | Stale cached client from a very old build; one hard refresh fixes it forever. |
| Installer says already installed | By design. Delete
data/config.php only for a true wipe. |
| "Could not write" in the console | File permissions on data/. |
| Callers get BUSY | All nodes in use; raise Max nodes or wait for the sweep. |
| Menu will not go back to generated | A leftover per-level backdrop variant is outranking the picker. Chapter 10.3. |
| Cron card red | The cron entry stopped; re-check the line and key. Pseudo-cron keeps the board alive meanwhile. |
| Locked out of the console | Five failed logins in 15 minutes; wait out the window. |
When the table does not have your symptom
Ask on the Support Forum. It covers ATDT and the rest of the BBS Preservation Project software, and an answer posted there stays where the next SysOp with the same problem can find it, which a reply to an email never does.
Worth bringing with you: your ATDT version (the console footer and the rail's version lamp both carry it), whether the board runs SQLite or MySQL, what your host is, and anything the events log said at the time. Most questions are answered by those four lines before anybody has to guess.
#Networking (coming in v2)
This chapter will cover joining a network, subscribing to areas, reading poll logs, and diagnosing dead links.
#Pipe color codes
|00 to |15 foreground, |16 to |23
background, || a literal pipe. Callers can read this same table on the board
through a HELP menu item.
#MCI variables
These expand everywhere text is displayed, whoever typed them, SysOp or caller: theme strings,
messages and mail (bodies and subjects), bulletins, oneliners, rumors, the auto-message, chat,
BBS-list notes, the broadcast banner, and inside .ans art (the connect, logon and
goodbye screens, menu backdrops, ART items, and art bulletins).
Each viewer sees their own values; the stored text keeps the codes. Unknown %-pairs pass
through as typed. On the connect screen, before login, %HN reads "caller".
Two ways a code fills in
A bare code pushes the row along. The value takes as much room as it needs and
everything after it on that row moves over. That is what a sentence wants: draw
%LC before you and the last caller's name slots in with the words following it.
Leave drawing room to the right.
An exclamation mark in front and the value stamps in place (new in 1.7.7). The value is written starting at the exclamation mark and runs rightward over whatever is already there, so the row comes out exactly as wide as it was drawn and nothing after it moves.
Which means: leave the cells to the right of a marked code clear. Give the code room for the longest value it will ever hold, and put nothing there you want to keep.
The rule of thumb: mark the codes inside boxes and tables, leave the ones in sentences bare. A frame keeps its right-hand border either way only if the code inside it is marked. The caller's own code guide, the HELP menu action, carries this rule too.
Since 1.7.7 a row is also cut at column 80 rather than wrapped. A value long enough to run off the right edge used to wrap onto the next line and push the whole picture down a row; now the rows under it stay where they were drawn, whichever way the code fills in.
| %HN | The caller's handle |
| %LV | Level |
| %ND | Node |
| %BN | Board name |
| %PH | Board number |
| %DT | Date, board clock |
| %TM | Time, board clock |
| %CT | Calls today |
| %CA | Calls ever |
| %LC | Last caller |
| %UT | Total users |
| %AN | Current area name |
| %AD | Current area description. New in 1.7.0. |
| %MC | Messages in area |
| %VN | ATDT version |
| %BD | The viewer's connection speed: their own throttle if set, otherwise the board's Line speed. Reads FAST when the throttle is off. New in 1.6.0. |
| %FA | The caller's current file area. New in 1.8.0, like the six below. |
| %FD | That file area's description |
| %FC | Files in that area |
| %FN | Files in it new to the caller |
| %FT | Files on the whole board |
| %FU | Files the caller has uploaded |
| %FP | The caller's file points; blank while points are off |
#Settings quick reference
| Setting | Page · one line |
|---|---|
| Board name / Base URL / Timezone | Settings · identity and the caller clock. |
| Board number | Settings · the ceremony's dial string; %PH. |
| Max nodes | Settings · simultaneous caller cap (10). |
| New user policy / question | Settings · approve, auto, closed. |
| BBS list additions | Settings · ACS to add directory entries. |
| Banned addresses | Settings · IPs (exact or prefix) refused before the ceremony. |
| iCE colors | Settings · bright backgrounds vs blink. |
| Connect ceremony | Settings · the fake handshake. |
| Allow user color | Settings · caller pipe codes render. |
| Default theme | Settings · what everyone sees unless set per caller. |
| Line speed | Settings · board default baud; new callers start here; the CONNECT number. |
| Idle hang-up | Settings · quiet minutes before the line lets go, any screen (30; 0 off). |
| SysOp chat style | Settings · classic scroll or split screen, as the caller sees it. |
| Prohibited words | Settings · handles refused at the application desk; three in a row drops the line. |
| SysOp notifications | Settings · pages as browser push, opt-in per browser, HTTPS only. |
| Outgoing mail | Settings · send-only email: resets, EMAILSYSOP, the email asks. |
| Cron key | Settings · guards cron.php. |
| Theme (per caller) | Users · "(board default)" or a specific wardrobe. |
| Email (per caller) | Users · where that caller's password resets go. |
| The logon tour | Settings · the order of the cards after the password, or none at all. New in 1.7.3. |
| Message list on arrival | Settings · Open or Folded, the state a caller finds a message list in. Open is the default. New in 1.7.9. |
| Console theme | Settings, This console · Dark, Light, or follow the browser. Dark is the default. New in 1.7.9. |
| Call log keep window | Settings, Advanced · how long call rows live before the prune tool takes them; a year, 0 for forever. New in 1.7.9. |
| Backup path / copies kept | Database, Backup · where backups are written, outside the web root, and how many are kept. New in 1.7.9. |
| File areas card | Settings · largest upload, minimum description, FILE_ID.DIZ, uploader shown, daily download limit, link minutes, ratio and grace, file points. Every economy off by default (23.3). New in 1.8.0. |
| File area / Default file area | Menus · the target of a file item, and where a section's callers start (23.4). New in 1.8.0. |
| Include file areas | Database, Backup · put the stock file folders in the backup. New in 1.8.0. |
| Points balance (per caller) | Users · set while file points are on. New in 1.8.0. |
| Show the door's status line | DOS Doors, per door · the game's own status line in the door bar. Off by default. New in 1.8.0. |
| Release check | Settings · once a day, learn the current release from the ATDT website; drives the version lamp. On by default. New in 1.7.8. |
| Center the console | Settings, This console · center the whole console on a wide window. Off by default. New in 1.7.8. |
| DOS doors | Settings · master switch for original DOS door games; off by default. New in 1.7.0. |
| Board offline | Settings · nobody connects, not even you, until it flips back. New in 1.7.0. |
| Last call (per caller) | Users · set or clear a caller's last call date. New in 1.7.0. |
| Listed | Areas · checked (default), the area appears in the general area-change list. Unchecked, it leaves that list and nothing else. Discovery, not security (9.3). New in 1.6.5. |
| Area scope | Menus · blank (default), this menu shares the board's current message area. A name: this menu keeps its own, shared with menus naming the same scope (10.4). New in 1.6.5. |
| Default area | Menus · the board a caller starts in the first time they read or post in this section. Blank: their first read shows the picker. Only meaningful with an Area scope. New in 1.6.5. |
| Area / Limit to category | Menus, item form · the item's second argument, shown only for read, post, newscan, setarea and setareaback (an area) and areachange (a category). See 10.2. New in 1.6.5. |
| Door enable / ACS / sort | Doors · which games, to whom, in what order. |
#What lives where
Back up data/. Everything else is replaceable from the release zip, except doors
you installed yourself.