Your BBS in Your Pocket: Push Notifications and the Mobile-Ready Phosphor
August 29, 2026
The old argument against BBSes — and self-hosted community servers generally — used to be simple: they’re not where you are. A terminal lives on a desk. Your community lives on your phone, in your pocket, buzzing you when something happens. We fixed that. Phosphor BBS is now mobile-ready in the way that matters: it can reach out and grab you when your community needs you, and put you back exactly where you were when you answer.
Here’s what shipped, and how the pieces fit together.
Device tokens: log in once per device
First, the server learned to recognize a device, not just a login. There’s a new user_devices table backed by a UserDeviceDao: each device registration issues a 256-bit token, and only the SHA-256 hash is stored at rest — the plaintext token never touches the database, so a database leak doesn’t leak credentials. Re-registering the same device name rotates the token; the previous one stops working the moment the new hash lands. There’s a TTL on tokens, validation happens server-side, and malformed or expired tokens are simply rejected.
Then the handshake learned to take a hint. Token-carrying clients skip the login screen entirely and land straight on the main menu, over three transports:
- Telnet: the token rides in as a NEW-ENVIRON variable (
BBS_AUTH), negotiated per RFC 1572. - SSH: the client runs a
bbs-auth <token>exec command in place of a shell. - Console: the local launcher passes the token directly.
This is the difference between typing a password on a phone keypad and… not doing that. One tap, already authenticated, already in.
The push gateway: your server speaks FCM
Second, the server grew a notification system. NotificationService is the interface; FCMNotificationService is the implementation — HTTP calls to FCM’s v1 API (/v1/projects/{projectId}/messages:send), one request per registered device token, OAuth2 bearer auth per send. If FCM hiccups or a token is stale, the failure is swallowed and logged. Push never breaks the send. Your message goes out even if someone’s phone is unreachable.
The hooks are wired where messages actually happen: a DM sent through chat and a local mail delivery both fire a push hook, which resolves the recipient’s registered device tokens and triggers a notification per device. If a user has a phone and a tablet registered, both light up.
Payloads with a destination
Third — and this is the part that makes it feel like one system instead of a pager bolted onto a terminal — every push carries a PushPayload with a sessionId and a targetScreen. The resolver derives that context from the recipient’s live state: an attached session gets its current screen; a detached persistent session gets its stored state; nobody in particular gets a sane default. And explicit context at the call site wins, so a specific screen can request where its notification should land.
Walk through the whole flow: someone DMs you while you’re out. Your phone buzzes. You tap it. The app connects with its device token, skips the login screen, the server re-attaches your persistent session, and you’re looking at that DM — not the main menu, not the board index. Three subsystems (device auth, session persistence, push) composed into a single gesture. That’s the mobile architecture, end to end.
What’s here and what’s landing
Shipped and running today: device tokens, handshake bypass, the FCM gateway, contextual payloads, and the menu item to detach your session when you walk away. iOS support is landing next — the client integration is built against a mock and the real APNs credentials are on the way, so an iPhone tap will re-attach the same way Android’s does. Token management UI and connection-timeout settings are queued behind that.
The point of all this isn’t “BBS, but with notifications.” It’s that a community you choose shouldn’t be quieter than a platform you’re trapped in. Your server should be allowed to say “someone’s looking for you” — on your hardware, with hashed tokens, with a payload that hands you the context instead of an ad.
Your community. Your terminal. Your rules.
See it live: open bbs.phosphorbbs.net:8088/terminal — it’s the same terminal UI from a phone browser, re-attaching to your session like the native clients will. Then follow #dtp (plus #digitalthirdplace and #socialterminal) for the mobile releases as they ship. I run a DTP server. Yours is a download away.