<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Dev Log on Phosphor BBS</title>
		<link>https://phosphorbbs.net/blog/</link>
		<description>Recent content in Dev Log on Phosphor BBS</description>
		<generator>Hugo</generator>
		<language>en-us</language>
		
		
		
		
			<lastBuildDate>Wed, 23 Sep 2026 00:00:00 +0000</lastBuildDate>
		
			<atom:link href="https://phosphorbbs.net/blog/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>Markdown in a Terminal: Building a MarkdownWidget for jterm</title>
				<link>https://phosphorbbs.net/blog/markdown-in-a-terminal-building-the-markdownwidget/</link>
				<pubDate>Wed, 23 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/markdown-in-a-terminal-building-the-markdownwidget/</guid>
				<description>&lt;p&gt;Every BBS has the same problem: text that wants to be formatted. Help screens with headings and bullet lists. News articles with paragraphs. Mail that would really use a code block for that error dump. The traditional answers are all bad in the same way — hard-coded ANSI sequences baked into strings, a private wiki-syntax nobody else can read, or walls of plain text with no structure at all.&lt;/p&gt;&#xA;&lt;p&gt;jterm now ships a third answer: a &lt;strong&gt;MarkdownWidget&lt;/strong&gt; that parses real markdown and renders it as styled terminal lines.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Publishing 0.1.1: The Deploy That Exited 0 and Published Nothing</title>
				<link>https://phosphorbbs.net/blog/publishing-0-1-1-the-deploy-that-exited-zero/</link>
				<pubDate>Wed, 23 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/publishing-0-1-1-the-deploy-that-exited-zero/</guid>
				<description>&lt;p&gt;jterm 0.1.1 is on Maven Central. The build that put it there was green in seventeen seconds of test time — and took nine and a half minutes of wall clock, plus a mid-flight correction when we discovered the first deploy had quietly published nothing at all. This post is the release notes for the &lt;em&gt;process&lt;/em&gt;, because the failure mode is one every maintainer of a Central-published library will hit.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The Case of the Blended Batches: A Race Hidden Inside a Replace</title>
				<link>https://phosphorbbs.net/blog/the-case-of-the-blended-batches/</link>
				<pubDate>Wed, 23 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/the-case-of-the-blended-batches/</guid>
				<description>&lt;p&gt;The jterm thread-safety suite exists to answer one question: &lt;em&gt;can a widget survive being redrawn from one thread while another mutates it?&lt;/em&gt; It has run thousands of times across dozens of widgets, mostly to say yes. On the morning we cut the 0.1.1 release, it said no — and the test that failed wasn&amp;rsquo;t even the one that was broken.&lt;/p&gt;&#xA;&lt;h2 id=&#34;two-failures-two-days-apart&#34;&gt;Two failures, two days apart&lt;/h2&gt;&#xA;&lt;p&gt;The release gate runs the whole suite, 2,926 tests. The first full run failed one test: &lt;code&gt;FireworksTest.renderFrameProducesOutput&lt;/code&gt; — the fireworks animation was supposed to paint visible pixels after five frames and, once out of 2,926, it painted nothing. We re-ran the class in isolation: 12/12 green. Read the render path: fresh instance, deterministic math, five calls that each draw a rocket or particles. The failure looked like noise under load — the kind of flake you shrug at and re-run.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Y/M/D and a Digit: Composing Chart Ranges from a Unit and a Number</title>
				<link>https://phosphorbbs.net/blog/chart-ranges-unit-and-amount/</link>
				<pubDate>Wed, 23 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/chart-ranges-unit-and-amount/</guid>
				<description>&lt;p&gt;The stock chart on Phosphor&amp;rsquo;s finance door had five time windows, chosen by five keys: 1D, 3M, 6M, 1Y, and 0 for &amp;ldquo;all history.&amp;rdquo; That&amp;rsquo;s the standard menu — every finance app has it. And like the standard menu, it had a wall you hit the first time you actually used it: you can&amp;rsquo;t ask for &lt;strong&gt;3Y&lt;/strong&gt;. Or 2M. Or 10D. Every range anyone might want is either pre-built or impossible.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Chat From Anywhere: The Ctrl-T Popup</title>
				<link>https://phosphorbbs.net/blog/chat-anywhere-with-the-ctrl-t-popup/</link>
				<pubDate>Sun, 20 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/chat-anywhere-with-the-ctrl-t-popup/</guid>
				<description>&lt;p&gt;On a traditional BBS, chat is a &lt;em&gt;place&lt;/em&gt;. You navigate to the chat section, you sit there, you talk. When you want to check your mail you leave chat — and the conversation — behind. That&amp;rsquo;s fine when chat is an event you schedule. It&amp;rsquo;s terrible when it&amp;rsquo;s ambient, the way a community actually works: someone drops a line into the channel while you&amp;rsquo;re reading the board, and you want to answer without losing your place.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The Case of the Very Random Dead Ctrl-T</title>
				<link>https://phosphorbbs.net/blog/the-case-of-the-very-random-dead-ctrl-t/</link>
				<pubDate>Sun, 20 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/the-case-of-the-very-random-dead-ctrl-t/</guid>
				<description>&lt;p&gt;Two weeks into the popup chat feature, users started reporting the same thing in different words: &lt;em&gt;Ctrl-T is very random.&lt;/em&gt; Sometimes it opened the chat popup instantly. Sometimes it did nothing — not even an error. Same terminal, same screen, same key. First press of the session would work, three presses in a row would work, then a press after closing the popup with ESC would go dead. Then it would work again. There was no pattern, which was the most maddening part — a consistently broken key is a bug report; an inconsistently broken key is a haunting.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Blackjack in Phosphor: A Door Game as a Language Test</title>
				<link>https://phosphorbbs.net/blog/blackjack-in-phosphor-a-door-game-as-a-language-test/</link>
				<pubDate>Sat, 19 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/blackjack-in-phosphor-a-door-game-as-a-language-test/</guid>
				<description>&lt;p&gt;Every language looks fine in its own test suite. The tests were written&#xA;by the same people who wrote the language, with the same blind spots.&#xA;The only honest benchmark is a program someone actually wants to run.&lt;/p&gt;&#xA;&lt;p&gt;So when the question came up — &amp;ldquo;would it be easy to create a simple&#xA;blackjack game for the BBS?&amp;rdquo; — the answer was: yes, and that&amp;rsquo;s exactly&#xA;the test Phosphor needs. Blackjack is a sweet spot for a scripting&#xA;language&amp;rsquo;s first real workload. It has genuine state (a shuffled deck,&#xA;two hands, a bankroll), real control flow (a dealer AI that hits to&#xA;17, ace soft/hard counting), string wrangling (card glyphs), user&#xA;input, and persistence. If the parser, the evaluator, and the door&#xA;bridge can carry all of that, the language is real. If they can&amp;rsquo;t, we&#xA;find out where.&lt;/p&gt;</description>
			</item>
			<item>
				<title>UserDefaults for a BBS: A Generic Preferences and State API</title>
				<link>https://phosphorbbs.net/blog/userdefaults-for-a-bbs-a-generic-preferences-and-state-api/</link>
				<pubDate>Sat, 19 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/userdefaults-for-a-bbs-a-generic-preferences-and-state-api/</guid>
				<description>&lt;p&gt;Every non-trivial app eventually faces the same question: where does&#xA;small user configuration live, and where does user &lt;em&gt;data&lt;/em&gt; live? macOS&#xA;answered this decades ago with two separate systems — &lt;code&gt;UserDefaults&lt;/code&gt;&#xA;for typed, user-visible settings, and the file system for documents.&#xA;We had been living with neither, and it showed.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-mess-we-had&#34;&gt;The mess we had&lt;/h2&gt;&#xA;&lt;p&gt;Phosphor already had a real preference engine. &lt;code&gt;PreferenceResolver&lt;/code&gt;&#xA;resolves settings through three levels — user, then group, then&#xA;global — backed by the database, cached with proper invalidation, and&#xA;connected across processes with Postgres &lt;code&gt;LISTEN/NOTIFY&lt;/code&gt;. Screens&#xA;could even bind to a preference reactively, so flipping a toggle&#xA;redraws every open screen instantly. For the language side, &lt;code&gt;.phos&lt;/code&gt;&#xA;scripts read settings with &lt;code&gt;pref(&amp;quot;key&amp;quot;)&lt;/code&gt; and write them with&#xA;&lt;code&gt;set_pref(&amp;quot;key&amp;quot;, value)&lt;/code&gt;.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Give Every Column Its Fair Share: Per-Column Widths in the jterm Table Widget</title>
				<link>https://phosphorbbs.net/blog/per-column-widths-in-the-jterm-table-widget/</link>
				<pubDate>Fri, 18 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/per-column-widths-in-the-jterm-table-widget/</guid>
				<description>&lt;p&gt;Tables are the workhorse of every BBS screen. Message lists, who&amp;rsquo;s online, file&#xA;areas, the sysop&amp;rsquo;s session dashboard — all of them are just rows and columns.&#xA;And until this week, every column in a jterm &lt;code&gt;Table&lt;/code&gt; got the same slice of the&#xA;screen. Seven columns at 80 characters? Eleven characters each, whether you&amp;rsquo;re&#xA;rendering a two-letter status flag or a 24-character username.&lt;/p&gt;&#xA;&lt;p&gt;Equal division is the correct default — it&amp;rsquo;s fair, it&amp;rsquo;s predictable, and it&#xA;requires the developer to decide nothing. But &amp;ldquo;requires no decisions&amp;rdquo; is a&#xA;polite way of saying &amp;ldquo;offers no control.&amp;rdquo; A session table&amp;rsquo;s &lt;em&gt;Screen&lt;/em&gt; column&#xA;wants room to breathe; its &lt;em&gt;Spy&lt;/em&gt; column (a two-character checkbox) is wasted&#xA;space at eleven characters wide. The information density of the screen was&#xA;being decided by arithmetic, not by design.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The Case of the Garbled Borders: Fixing SyncTERM Support</title>
				<link>https://phosphorbbs.net/blog/the-case-of-the-garbled-borders-fixing-syncterm-support/</link>
				<pubDate>Fri, 18 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/the-case-of-the-garbled-borders-fixing-syncterm-support/</guid>
				<description>&lt;p&gt;Every BBS lives or dies by its client support. MuffinTerm works. The web&#xA;client works. And then a user pointed out that the most popular terminal&#xA;program in the BBS world — SyncTERM, the client that most of the people&#xA;dialing into boards in 2026 are actually using — rendered every screen as&#xA;mojibake. Box borders turned into &lt;code&gt;┬í┬┐&lt;/code&gt; soup. The login screen was&#xA;unreadable. Our own sysop confirmed it the same evening from his own&#xA;machine: &amp;ldquo;completely messed up.&amp;rdquo;&lt;/p&gt;</description>
			</item>
			<item>
				<title>The Doorbell for the Dev Blog: Why We Ship an RSS Feed</title>
				<link>https://phosphorbbs.net/blog/the-doorbell-for-the-dev-blog-our-rss-feed/</link>
				<pubDate>Thu, 17 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/the-doorbell-for-the-dev-blog-our-rss-feed/</guid>
				<description>&lt;p&gt;Every post from this dev log — 39 of them now, from &amp;ldquo;Why I&amp;rsquo;m Building a BBS in 2026&amp;rdquo; to this morning&amp;rsquo;s piece on the three-door security model — is available over RSS at:&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://phosphorbbs.net/index.xml&#34;&gt;https://phosphorbbs.net/index.xml&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Paste that into any feed reader and the posts come to you as they publish. That&amp;rsquo;s the whole feature. But it&amp;rsquo;s worth a short post, because RSS is doing something specific for this project, and because most readers stopped being shown how feeds work about fifteen years ago.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Whitelist, Gray List, Blacklist: The Three-Door Security Model</title>
				<link>https://phosphorbbs.net/blog/whitelist-gray-list-blacklist-the-three-door-security-model/</link>
				<pubDate>Thu, 17 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/whitelist-gray-list-blacklist-the-three-door-security-model/</guid>
				<description>&lt;p&gt;A community server needs doors with different rules. Some addresses should always get in. Some burned their welcome and should cool off. And a few — after a human looked at what they did — should never come back, from any transport, ever.&lt;/p&gt;&#xA;&lt;p&gt;Phosphor&amp;rsquo;s connection security grew one layer at a time, and the result is a three-list model that&amp;rsquo;s worth explaining as a unit, because each list answers a different question.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Page Sysop: The Classic BBS Ritual Gets a Phone Push</title>
				<link>https://phosphorbbs.net/blog/page-sysop-the-classic-bbs-ritual-with-a-modern-twist/</link>
				<pubDate>Wed, 16 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/page-sysop-the-classic-bbs-ritual-with-a-modern-twist/</guid>
				<description>&lt;p&gt;Every classic BBS had a ritual for &lt;em&gt;I need a human right now&lt;/em&gt;: page the sysop. It was the doorbell of the system — one keypress, a line of text, and somewhere in the house a person heard a chime and knew someone was waiting. Legacy boards grew it organically because they had a specific human property: the sysop was a &lt;em&gt;person in a room&lt;/em&gt;, not a support ticket queue.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Five Bugs in One Morning: Debugging the Phosphor iOS Client</title>
				<link>https://phosphorbbs.net/blog/five-bugs-in-one-morning-debugging-the-phosphor-ios-client/</link>
				<pubDate>Fri, 04 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/five-bugs-in-one-morning-debugging-the-phosphor-ios-client/</guid>
				<description>&lt;p&gt;The &lt;a href=&#34;https://phosphorbbs.net/blog/a-qr-code-on-a-text-screen-pairing-phones-to-a-bbs-without-a-login&#34;&gt;QR pairing post&lt;/a&gt; ended with a working native iOS client for Phosphor BBS. What it didn&amp;rsquo;t cover is what happened next: the app crashed randomly, the keyboard never appeared, and the whole UI rendered in a sad little window in the middle third of the screen. One morning of debugging later, every bug had a root cause, and every root cause was a lesson worth writing down.&lt;/p&gt;&#xA;&lt;p&gt;This is a war story. Five bugs, five root causes, and the one thread that ties them together: &lt;strong&gt;things that pass every test and still fail on real hardware.&lt;/strong&gt;&lt;/p&gt;</description>
			</item>
			<item>
				<title>The Screen That Lied: Building Idle Timers That Actually Tick</title>
				<link>https://phosphorbbs.net/blog/idle-timers-that-actually-tick-window-auto-refresh/</link>
				<pubDate>Fri, 04 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/idle-timers-that-actually-tick-window-auto-refresh/</guid>
				<description>&lt;p&gt;Here&amp;rsquo;s a bug report you can&amp;rsquo;t reproduce with a test: &lt;em&gt;&amp;ldquo;the sessions view shows a list of users logged in, and when they change state Connected → disconnected the display updates immediately — but the idle time doesn&amp;rsquo;t update. If I quit the window and reopen it, the idle times are current again.&amp;rdquo;&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;The sysop was right, and the cause was architectural. Every screen in &lt;a href=&#34;https://phosphorbbs.net&#34;&gt;Phosphor BBS&lt;/a&gt; is drawn by our own terminal UI toolkit, jterm — a pure-Java, lanterna-style TUI framework with double-buffered, diff-based refresh. That diff-based refresh is the crown jewel: when you redraw, you only pay for the cells that changed. But it had a blind spot.&lt;/p&gt;</description>
			</item>
			<item>
				<title>A QR Code on a Text Screen: Pairing Phones to a BBS Without a Login</title>
				<link>https://phosphorbbs.net/blog/a-qr-code-on-a-text-screen-pairing-phones-to-a-bbs-without-a-login/</link>
				<pubDate>Wed, 02 Sep 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/a-qr-code-on-a-text-screen-pairing-phones-to-a-bbs-without-a-login/</guid>
				<description>&lt;p&gt;There&amp;rsquo;s a moment in every mobile-client story where the design gets embarrassing. Your BBS just grew a beautiful native iOS app — SwiftUI, an embedded terminal, SSH, the works. And then someone asks the question that matters: &lt;em&gt;how does the phone prove it&amp;rsquo;s you?&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;The boring answer is a login form on a touchscreen. Type your username. Type your password. Maybe paste a token. On a touch keyboard. For a terminal system whose whole identity is that it never needed a GUI.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Ctrl&#43;C to Step Away: Keyboard Shortcuts for Phosphor&#39;s Session Persistence</title>
				<link>https://phosphorbbs.net/blog/ctrl-c-to-step-away-keyboard-shortcuts-for-phosphor-session-persistence/</link>
				<pubDate>Mon, 31 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/ctrl-c-to-step-away-keyboard-shortcuts-for-phosphor-session-persistence/</guid>
				<description>&lt;p&gt;Last week we shipped session persistence for Phosphor BBS: detach your session, close your terminal, reconnect later, and your screen, cursor, and half-finished input are exactly where you left them. The &lt;a href=&#34;https://phosphorbbs.net/blog/tmux-for-your-bbs-phosphor-sessions-now-survive-disconnects&#34;&gt;first post&lt;/a&gt; covered the detach/reattach architecture. This post is about the keyboard shortcuts we built to make it feel right.&lt;/p&gt;&#xA;&lt;p&gt;Because the hardest part of session persistence isn&amp;rsquo;t keeping the state alive — it&amp;rsquo;s making the exit feel natural.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-key-binding-problem&#34;&gt;The key binding problem&lt;/h2&gt;&#xA;&lt;p&gt;A BBS is not a shell. When you SSH into a Linux box and hit Ctrl+C, you&amp;rsquo;re sending SIGINT to the foreground process. When you hit ESC in vim, you&amp;rsquo;re entering normal mode. These are deep muscle memories, and every terminal application has to decide how to honor or override them.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Lite Emacs in Your BBS: The Key Bindings That Make Phosphor&#39;s Text Fields Work</title>
				<link>https://phosphorbbs.net/blog/lite-emacs-in-your-bbs-the-key-bindings-that-make-phosphors-text-fields-work/</link>
				<pubDate>Mon, 31 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/lite-emacs-in-your-bbs-the-key-bindings-that-make-phosphors-text-fields-work/</guid>
				<description>&lt;p&gt;If you&amp;rsquo;re the kind of person who reaches for Ctrl+A to jump to the beginning of a line, or Ctrl+K to delete everything from the cursor to the end, Phosphor&amp;rsquo;s text fields already speak your language. Every text input in the BBS — username, password, chat message, board post, search query — uses the same set of emacs-inspired key bindings, alongside the arrow keys and Home/End you&amp;rsquo;d expect.&lt;/p&gt;&#xA;&lt;p&gt;This is a reference post. Bookmark it.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The Case for Running Your Own Digital Third Place</title>
				<link>https://phosphorbbs.net/blog/the-case-for-running-your-own-digital-third-place/</link>
				<pubDate>Sat, 29 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/the-case-for-running-your-own-digital-third-place/</guid>
				<description>&lt;p&gt;There&amp;rsquo;s a sentence we keep coming back to: &lt;strong&gt;&amp;ldquo;I run a DTP server.&amp;rdquo;&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;DTP stands for &lt;em&gt;digital third place&lt;/em&gt;. If you know Ray Oldenburg&amp;rsquo;s work, the third place is neither home nor work — it&amp;rsquo;s the barbershop, the bowling league, the café where the staff knows your order. Sociologists have spent forty years explaining why these places hold communities together, and for the last decade the internet&amp;rsquo;s best versions of them have been run by companies that turn your community into their product. This post is the case for running the third place yourself — on a DTP server, a category of software that now exists because Phosphor made it real.&lt;/p&gt;</description>
			</item>
			<item>
				<title>tmux for Your BBS: Phosphor Sessions Now Survive Disconnects</title>
				<link>https://phosphorbbs.net/blog/tmux-for-your-bbs-phosphor-sessions-now-survive-disconnects/</link>
				<pubDate>Sat, 29 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/tmux-for-your-bbs-phosphor-sessions-now-survive-disconnects/</guid>
				<description>&lt;p&gt;If you&amp;rsquo;ve used tmux or screen, you already understand what we just shipped for Phosphor BBS: the ability to walk away. Close the laptop. Lose the train tunnel Wi-Fi. Kill the app by accident. Come back — and everything is exactly where you left it.&lt;/p&gt;&#xA;&lt;p&gt;That&amp;rsquo;s now how sessions work on a Phosphor DTP server. And it changes what kind of place your community server can be.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-problem-a-socket-is-not-a-person&#34;&gt;The problem: a socket is not a person&lt;/h2&gt;&#xA;&lt;p&gt;Traditional BBS software — and, honestly, most modern chat infrastructure — ties a user&amp;rsquo;s session to a network connection. The socket closes, the connection dies, and everything the user was doing evaporates. You were halfway through writing a long post, three screens deep into a file area, mid-conversation in a chat channel. Gone. Reconnect and you&amp;rsquo;re back at the login prompt, starting over.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Your BBS in Your Pocket: Push Notifications and the Mobile-Ready Phosphor</title>
				<link>https://phosphorbbs.net/blog/your-bbs-in-your-pocket-push-notifications-and-the-mobile-ready-phosphor/</link>
				<pubDate>Sat, 29 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/your-bbs-in-your-pocket-push-notifications-and-the-mobile-ready-phosphor/</guid>
				<description>&lt;p&gt;The old argument against BBSes — and self-hosted community servers generally — used to be simple: &lt;em&gt;they&amp;rsquo;re not where you are.&lt;/em&gt; 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.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Live Spellcheck in a Terminal: Yellow Highlights, No Popups</title>
				<link>https://phosphorbbs.net/blog/live-spellcheck-in-a-terminal-yellow-highlights-no-popups/</link>
				<pubDate>Sat, 15 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/live-spellcheck-in-a-terminal-yellow-highlights-no-popups/</guid>
				<description>&lt;p&gt;Every modern editor highlights misspelled words as you type. Squiggly red underlines in Word, yellow backgrounds in Google Docs, dotted lines in VS Code. It&amp;rsquo;s so standard you forget it&amp;rsquo;s there — until it isn&amp;rsquo;t.&lt;/p&gt;&#xA;&lt;p&gt;Terminals don&amp;rsquo;t have spellcheck. The terminal is a character grid. There&amp;rsquo;s no DOM, no CSS, no per-character styling primitive. Or so the conventional wisdom goes.&lt;/p&gt;&#xA;&lt;p&gt;We just shipped live inline spellcheck in jterm and Phosphor BBS. Misspelled words light up in yellow as you type — in chat, board posts, mail compose, any text field. No popups, no pre-submit prompts, no context switches. Just yellow where the typos are.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Ghost Text Completion: Bringing Modern Editor UX to the Terminal</title>
				<link>https://phosphorbbs.net/blog/ghost-text-completion-bringing-modern-editor-ux-to-the-terminal/</link>
				<pubDate>Fri, 14 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/ghost-text-completion-bringing-modern-editor-ux-to-the-terminal/</guid>
				<description>&lt;p&gt;If you&amp;rsquo;ve used VS Code, fish shell, or Google&amp;rsquo;s search bar, you&amp;rsquo;ve seen ghost text — that dim, semi-transparent suggestion that appears ahead of your cursor as you type. You ignore it if it&amp;rsquo;s wrong. You press Tab to accept it if it&amp;rsquo;s right. It never gets in your way, but when it works, it saves you keystrokes.&lt;/p&gt;&#xA;&lt;p&gt;We just shipped ghost text completion in jterm and Phosphor BBS. Every text input — chat messages, board posts, mail compose, even the mail &amp;ldquo;To&amp;rdquo; field — now suggests completions as you type. Press Tab to accept. Press anything else to dismiss.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Animated Borders: Living Frames in a Terminal UI Toolkit</title>
				<link>https://phosphorbbs.net/blog/animated-borders-in-a-terminal-ui-toolkit/</link>
				<pubDate>Wed, 12 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/animated-borders-in-a-terminal-ui-toolkit/</guid>
				<description>&lt;p&gt;A border in a terminal UI is usually a static thing. Four corners, four edges, drawn once and forgotten. Box-drawing characters sit there like a picture frame — functional, boring, dead.&lt;/p&gt;&#xA;&lt;p&gt;jterm&amp;rsquo;s new AnimatedBorder system changes that. Borders can now sparkle, march, rotate, pulse, and scan. The login dialog in Phosphor BBS picks one at random for every new connection, so each user sees a different animated frame when they log in. The terminal isn&amp;rsquo;t a static page anymore — it&amp;rsquo;s alive, even down to the border.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Designing Reusable Config Screens: From Vertical Labels to Table Layout</title>
				<link>https://phosphorbbs.net/blog/designing-reusable-config-screens/</link>
				<pubDate>Wed, 12 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/designing-reusable-config-screens/</guid>
				<description>&lt;p&gt;Every config screen in Phosphor BBS used to be a snowflake. SystemConfigScreen had its own layout. AiConfigScreen had its own layout. They looked different, behaved differently, and shared no code. Adding a new settings screen meant copying one of them, stripping out what you didn&amp;rsquo;t need, and writing the rest from scratch.&lt;/p&gt;&#xA;&lt;p&gt;This is the story of how we fixed that — extracting a reusable &lt;code&gt;TableConfigScreen&lt;/code&gt; parent class and converting every config screen to the same table-based layout, killing about 150 lines of boilerplate in the process.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The Auto-Approve Dead-End: A BBS Onboarding Bug Story</title>
				<link>https://phosphorbbs.net/blog/the-auto-approve-dead-end/</link>
				<pubDate>Wed, 12 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/the-auto-approve-dead-end/</guid>
				<description>&lt;p&gt;Here&amp;rsquo;s a bug that&amp;rsquo;s easy to introduce and embarrassing to discover: a new user creates an account on your BBS, the system auto-approves them, generates a temporary password, and sends it to their BBS mailbox. The user can now read that password — by logging in. Which requires the password. Which is in the mailbox. Which they can&amp;rsquo;t open.&lt;/p&gt;&#xA;&lt;p&gt;Classic chicken-and-egg. Let me walk through how this happened, why it was hard to spot, and how we fixed it.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Hal: An AI SysOp That Never Leaves the Server</title>
				<link>https://phosphorbbs.net/blog/hal-an-ai-sysop-that-never-leaves-the-server/</link>
				<pubDate>Fri, 07 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/hal-an-ai-sysop-that-never-leaves-the-server/</guid>
				<description>&lt;p&gt;Phosphor has a staff member now. His name is Hal, he listens on the &lt;code&gt;#sysop&lt;/code&gt; channel and to direct messages, and he can answer &amp;ldquo;who&amp;rsquo;s online,&amp;rdquo; look up connection logs, walk through board stats, or take care of routine admin work — while the sysop is doing something else. Everything he knows and does stays on the machine the BBS runs on.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-off-grid-constraint&#34;&gt;The off-grid constraint&lt;/h2&gt;&#xA;&lt;p&gt;The design rule that shaped everything: &lt;strong&gt;AI features use local Ollama only. No cloud APIs.&lt;/strong&gt; A community server whose value proposition is &lt;em&gt;you own the place&lt;/em&gt; cannot quietly forward your users&amp;rsquo; conversations to a third party. Hal runs against &lt;code&gt;localhost:11434&lt;/code&gt;, silently disables if Ollama is down, and is opt-in, off by default. If the network is gone, Hal keeps working — which matters for a server that&amp;rsquo;s supposed to run through anything.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Two Dialects, One Schema: Supporting H2 and Postgres Without Losing Your Mind</title>
				<link>https://phosphorbbs.net/blog/two-dialects-one-schema-h2-and-postgres/</link>
				<pubDate>Fri, 07 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/two-dialects-one-schema-h2-and-postgres/</guid>
				<description>&lt;p&gt;A BBS should boot on a laptop with no database server installed. It should also run a production community for years on a real database with real operational tools. Those are different requirements, and Phosphor satisfies both by maintaining &lt;strong&gt;one schema in two dialects&lt;/strong&gt;: PostgreSQL for production, embedded H2 for zero-config installs.&lt;/p&gt;&#xA;&lt;p&gt;This post is the field guide to what that actually costs — the failure modes, the patterns that keep them manageable, and the bugs we hit so you don&amp;rsquo;t have to.&lt;/p&gt;</description>
			</item>
			<item>
				<title>From IRC to iMessage: Rebuilding BBS Chat for 2026</title>
				<link>https://phosphorbbs.net/blog/from-irc-to-imessage-rebuilding-bbs-chat-for-2026/</link>
				<pubDate>Mon, 03 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/from-irc-to-imessage-rebuilding-bbs-chat-for-2026/</guid>
				<description>&lt;p&gt;The original BBS chat was IRC. You&amp;rsquo;d type &lt;code&gt;/join #lobby&lt;/code&gt;, see messages scroll by in a flat log — &lt;code&gt;&amp;lt;joe&amp;gt; hey everyone&lt;/code&gt; — and if you wanted to talk to someone privately, you&amp;rsquo;d type &lt;code&gt;/msg joe hey man&lt;/code&gt;. It worked. It was 1992.&lt;/p&gt;&#xA;&lt;p&gt;But nobody talks like that anymore. Your phone shows messages as bubbles. Group chats have avatars and timestamps that fade into the background. You tap a channel name to switch rooms. You @-mention people. The IRC command syntax feels like a foreign language to anyone who grew up with iMessage and Telegram.&lt;/p&gt;</description>
			</item>
			<item>
				<title>How to Build a Digital Third Place That&#39;s Actually Yours</title>
				<link>https://phosphorbbs.net/blog/how-to-build-a-digital-third-place/</link>
				<pubDate>Sun, 02 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/how-to-build-a-digital-third-place/</guid>
				<description>&lt;p&gt;You&amp;rsquo;ve read about digital third places. You understand the problem — Discord isn&amp;rsquo;t yours, Slack is for work, X is a firehose, Reddit sold your API access. You want a community space you actually own.&lt;/p&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s how to build one.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-a-real-third-place-needs&#34;&gt;What a real third place needs&lt;/h2&gt;&#xA;&lt;p&gt;Before the how, the what. A digital third place needs five things:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Persistence.&lt;/strong&gt; The space exists whether you&amp;rsquo;re there or not. Messages stay. History builds. The community has memory.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ownership.&lt;/strong&gt; You control the server, the data, the rules. No platform can change the deal.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Low friction.&lt;/strong&gt; People can join without downloading an app, verifying a phone number, or accepting a 47-page terms of service.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Regulars.&lt;/strong&gt; People who come back, know each other, and notice when someone&amp;rsquo;s missing.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Conversation first.&lt;/strong&gt; The main activity is talking to people — not scrolling a feed, not playing an algorithm.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;If your community platform fails any of these, it&amp;rsquo;s not a third place. It&amp;rsquo;s a product you&amp;rsquo;re using until the company that owns it decides otherwise.&lt;/p&gt;</description>
			</item>
			<item>
				<title>One Platform for Three Things You&#39;re Doing in Three Places</title>
				<link>https://phosphorbbs.net/blog/one-platform-three-things/</link>
				<pubDate>Sun, 02 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/one-platform-three-things/</guid>
				<description>&lt;p&gt;You use three different tools for three different kinds of communication. You probably don&amp;rsquo;t think about it this way, but you do.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Slack or Discord for chat.&lt;/strong&gt; Real-time, instant, conversational. You&amp;rsquo;re talking &lt;em&gt;with&lt;/em&gt; people right now. Messages flow, responses come in seconds, the conversation moves fast. It&amp;rsquo;s great for &amp;ldquo;what are we doing right now&amp;rdquo; and terrible for &amp;ldquo;what did we decide last month.&amp;rdquo;&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;X or Mastodon for broadcasting.&lt;/strong&gt; One-to-many, short-form, public. You&amp;rsquo;re talking &lt;em&gt;at&lt;/em&gt; people. A post goes out, it reaches followers, replies trickle in. It&amp;rsquo;s great for &amp;ldquo;look at this&amp;rdquo; and terrible for &amp;ldquo;let&amp;rsquo;s discuss this in depth.&amp;rdquo;&lt;/p&gt;</description>
			</item>
			<item>
				<title>The Internet You Visit on Purpose</title>
				<link>https://phosphorbbs.net/blog/the-internet-you-visit-on-purpose/</link>
				<pubDate>Sun, 02 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/the-internet-you-visit-on-purpose/</guid>
				<description>&lt;p&gt;There&amp;rsquo;s a feeling people have about the old internet that they can&amp;rsquo;t quite name. They remember it — or feel like they should remember it — as a place you &lt;em&gt;went&lt;/em&gt;. You connected to something. You arrived somewhere. You were there on purpose, and when you were done, you left.&lt;/p&gt;&#xA;&lt;p&gt;The modern internet doesn&amp;rsquo;t work like that. It comes to you. It&amp;rsquo;s in your pocket, on your wrist, in your glasses. It pushes notifications, feeds, stories, reels, alerts. You don&amp;rsquo;t visit it. It visits you — constantly, relentlessly, whether you asked it to or not.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The Third Place Problem With Discord</title>
				<link>https://phosphorbbs.net/blog/the-third-place-problem-with-discord/</link>
				<pubDate>Sun, 02 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/the-third-place-problem-with-discord/</guid>
				<description>&lt;p&gt;Discord is the most successful digital third place ever built. 200 million people use it every month. Millions of communities live there — gaming groups, study circles, maker spaces, open source projects, friend groups, neighborhoods. It&amp;rsquo;s where people go to hang out.&lt;/p&gt;&#xA;&lt;p&gt;And it&amp;rsquo;s being sold out from under them.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-pattern&#34;&gt;The pattern&lt;/h2&gt;&#xA;&lt;p&gt;Every platform that becomes a third place goes through the same cycle:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Launch.&lt;/strong&gt; Free, open, no ads, no friction. &amp;ldquo;We&amp;rsquo;ll never sell out.&amp;rdquo; The community grows because it feels safe.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Growth.&lt;/strong&gt; Investment pours in. The platform scales. Features ship. The community deepens. People invest years building their space.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Monetization pressure.&lt;/strong&gt; Investors want returns. The platform needs revenue. Ads appear. Premium tiers launch. Data gets harvested.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Enshittification.&lt;/strong&gt; The community becomes ad inventory. The experience degrades. The rules change. The third place you built is now a storefront, and you&amp;rsquo;re the product.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;This isn&amp;rsquo;t hypothetical. It&amp;rsquo;s a documented pattern.&lt;/p&gt;</description>
			</item>
			<item>
				<title>What Is a Digital Third Place?</title>
				<link>https://phosphorbbs.net/blog/what-is-a-digital-third-place/</link>
				<pubDate>Sun, 02 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/what-is-a-digital-third-place/</guid>
				<description>&lt;p&gt;In 1989, sociologist Ray Oldenburg wrote &lt;em&gt;The Great Good Place&lt;/em&gt; and gave a name to something everyone already knew: we need three places. The first place is home. The second place is work. And the third place is the somewhere-else — the pub, the café, the barbershop, the park bench — where you go not to live or to produce, but to &lt;em&gt;be&lt;/em&gt;. To be around people. To belong to something that isn&amp;rsquo;t your family and isn&amp;rsquo;t your employer.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Federated BBS: How Phosphor Makes Multi-Node Sync Declarative</title>
				<link>https://phosphorbbs.net/blog/federated-bbs-how-phosphor-makes-multi-node-sync-declarative/</link>
				<pubDate>Fri, 31 Jul 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/federated-bbs-how-phosphor-makes-multi-node-sync-declarative/</guid>
				<description>&lt;p&gt;Every BBS in the 80s and 90s was an island. Your callers dialed your node. Your boards lived on your machine. If you wanted to share content with another sysop, you mailed a floppy.&lt;/p&gt;&#xA;&lt;p&gt;Phosphor changes that. Federation is now declarative — you write 10 lines of Phosphor instead of 200 lines of custom Java protocol code.&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-problem&#34;&gt;The Problem&lt;/h3&gt;&#xA;&lt;p&gt;Today, adding a new syncable resource to a BBS means writing custom Java serialization, a custom message type, a custom deserializer on the receiving end, and custom conflict resolution. This is why most BBS systems only sync boards and chat messages — everything else is too much work.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Phosphor Progress — From Parser to Federation</title>
				<link>https://phosphorbbs.net/blog/phosphor-progress-from-parser-to-federation/</link>
				<pubDate>Fri, 31 Jul 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/phosphor-progress-from-parser-to-federation/</guid>
				<description>&lt;p&gt;Twenty-nine commits. Six phases. One language. Here&amp;rsquo;s where Phosphor stands after the most intense development sprint yet.&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-journey-so-far&#34;&gt;The Journey So Far&lt;/h3&gt;&#xA;&lt;p&gt;When I wrote about &lt;a href=&#34;https://phosphorbbs.net/blog/building-the-phosphor-parser/&#34;&gt;building the Phosphor parser&lt;/a&gt;, the language was a lexer and a dream. Phase 1 was five tasks — tokenizer, parser, declarative processor, hot-reload, BBS wiring. It felt like a lot at the time.&lt;/p&gt;&#xA;&lt;p&gt;It wasn&amp;rsquo;t.&lt;/p&gt;&#xA;&lt;h3 id=&#34;phases-1-2-foundation&#34;&gt;Phases 1-2: Foundation&lt;/h3&gt;&#xA;&lt;p&gt;The declarative layer came first. Define your BBS structure — menus, boards, channels, file areas, themes — in a readable syntax. Save the file. The BBS syncs to the database automatically. No restart, no recompile.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Building a Lexer and Parser for a BBS Programming Language</title>
				<link>https://phosphorbbs.net/blog/building-a-lexer-and-parser-for-a-bbs-language/</link>
				<pubDate>Thu, 30 Jul 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/building-a-lexer-and-parser-for-a-bbs-language/</guid>
				<description>&lt;p&gt;How do you build a programming language for a BBS? You start with the same tools every language uses: a lexer to break source code into tokens, and a parser to turn tokens into a tree. This is the story of how Phosphor&amp;rsquo;s lexer and parser work, with real code from the implementation.&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-design&#34;&gt;The Design&lt;/h3&gt;&#xA;&lt;p&gt;Phosphor is a domain-specific language for BBS configuration and behavior. It has two layers:&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Declarative&lt;/strong&gt; — describe the BBS structure: menus, boards, channels, file areas, themes.&#xA;&lt;strong&gt;Imperative&lt;/strong&gt; — define behavior with event handlers, expressions, and control flow.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Declarative UI: Building Terminal Screens with Widgets in Phosphor</title>
				<link>https://phosphorbbs.net/blog/declarative-ui-building-terminal-screens-with-widgets/</link>
				<pubDate>Thu, 30 Jul 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/declarative-ui-building-terminal-screens-with-widgets/</guid>
				<description>&lt;p&gt;Most BBS systems render screens the hard way: imperative code that clears the terminal, prints line by line, and redraws on every update. It works, but it&amp;rsquo;s verbose and fragile. One missed redraw and the screen is stale.&lt;/p&gt;&#xA;&lt;p&gt;Phosphor takes a different approach. You describe the screen as a tree of widgets. The runtime handles rendering, re-rendering on data change, and input routing. You only write callbacks for interactive behavior.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Building the Phosphor Parser — Week 1 Dev Log</title>
				<link>https://phosphorbbs.net/blog/building-the-phosphor-parser/</link>
				<pubDate>Wed, 29 Jul 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/building-the-phosphor-parser/</guid>
				<description>&lt;p&gt;The first phase of Phosphor implementation is underway. Here&amp;rsquo;s what&amp;rsquo;s happening and why it matters.&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-problem&#34;&gt;The Problem&lt;/h3&gt;&#xA;&lt;p&gt;Every BBS system has the same issue: configuration is either too rigid (hardcoded in the application) or too generic (a config file that can&amp;rsquo;t express behavior). You want to add a new menu item? Edit Java, recompile, restart. You want a custom login handler? Write a plugin, package it, deploy it. You want to send mail to new users automatically? More Java, more compilation, more restarts.&lt;/p&gt;</description>
			</item>
			<item>
				<title>ANSI Sprites: Animation in a Terminal UI Toolkit</title>
				<link>https://phosphorbbs.net/blog/ansi-sprites-animation-in-a-terminal-ui-toolkit/</link>
				<pubDate>Tue, 28 Jul 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/ansi-sprites-animation-in-a-terminal-ui-toolkit/</guid>
				<description>&lt;p&gt;A terminal is a grid of characters. Each cell holds one glyph, one foreground color, one background color. That&amp;rsquo;s it. There are no pixels, no sprites, no animation frames. At least, that&amp;rsquo;s what you&amp;rsquo;d think.&lt;/p&gt;&#xA;&lt;p&gt;jterm&amp;rsquo;s sprite library takes that grid and turns it into a animation engine. ANSI art frames become sprite frames. A sprite sheet — a single ANSI file with a grid of cells — becomes a flipbook. Virtual threads drive the animation loop. And the terminal becomes a screen.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Threading the Flood: How Echomail Learned to Stay in Line</title>
				<link>https://phosphorbbs.net/blog/threading-echomail-uuids-timestamps-routing/</link>
				<pubDate>Sun, 19 Jul 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/threading-echomail-uuids-timestamps-routing/</guid>
				<description>&lt;p&gt;Federation is easy to demo and hard to make boring. The exciting part — a post appears on three servers — takes a weekend. The boring part, where the same post shows up in the right thread, with the right timestamp, exactly once, on every node, takes a month of small fixes. This is that month, told through echomail: Phosphor&amp;rsquo;s flooded, group-addressed message type, the modern replacement for the classic echo areas.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Some Rooms Are Yours Alone: Local-Only Boards and Export Control</title>
				<link>https://phosphorbbs.net/blog/local-only-boards-export-control/</link>
				<pubDate>Thu, 02 Jul 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/local-only-boards-export-control/</guid>
				<description>&lt;p&gt;The moment you connect your community server to federation, you&amp;rsquo;ve made a promise on behalf of everyone who posts there: &lt;em&gt;what&amp;rsquo;s written here travels&lt;/em&gt;. For a public board that&amp;rsquo;s the point. For the board where a handful of regulars plan the group&amp;rsquo;s next event — or anything else that was only ever meant for the local room — that promise is a privacy incident waiting to happen.&lt;/p&gt;&#xA;&lt;p&gt;So Phosphor made the boundary explicit, per board, at the schema level.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Terminal Animations: Starfields, Warps, and Living Backgrounds</title>
				<link>https://phosphorbbs.net/blog/terminal-animations-starfields-warps-and-living-backgrounds/</link>
				<pubDate>Sun, 21 Jun 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/terminal-animations-starfields-warps-and-living-backgrounds/</guid>
				<description>&lt;p&gt;A BBS login screen used to be a static ASCII banner. You&amp;rsquo;d connect, see a logo made of text characters, type your username and password, and that was it. No motion, no life, no atmosphere.&lt;/p&gt;&#xA;&lt;p&gt;jterm changes that. The login screen in Phosphor BBS has a living, animated background — stars twinkling, plasma flowing, cells dividing. Every time a user connects, the system randomly selects one of six animated backgrounds and renders it behind the login form. The terminal isn&amp;rsquo;t a static page anymore. It&amp;rsquo;s a window into a small, alive world.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Message Boards and Mail: Persistent Communication in Phosphor BBS</title>
				<link>https://phosphorbbs.net/blog/message-boards-and-mail-persistent-communication-in-phosphor-bbs/</link>
				<pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/message-boards-and-mail-persistent-communication-in-phosphor-bbs/</guid>
				<description>&lt;p&gt;A BBS without message boards is just a chat room. Boards are where the community lives — threaded discussions that persist over days, weeks, months. You log in, catch up on what you missed, reply to threads, and start new ones. It&amp;rsquo;s asynchronous communication at its best.&lt;/p&gt;&#xA;&lt;p&gt;Mail is the private counterpart — user-to-user messages that nobody else can read. Together, boards and mail form the communication backbone of the BBS.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Real-Time Chat on a BBS: Pub/Sub, Channels, and Wall Messages</title>
				<link>https://phosphorbbs.net/blog/real-time-chat-on-a-bbs-pubsub-channels-and-wall-messages/</link>
				<pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/real-time-chat-on-a-bbs-pubsub-channels-and-wall-messages/</guid>
				<description>&lt;p&gt;Chat is the heartbeat of a BBS. In the 90s, you&amp;rsquo;d log in, see who was online, and jump into a channel. Messages appeared character by character as the other person typed. It felt alive.&lt;/p&gt;&#xA;&lt;p&gt;Phosphor BBS brings that feeling back — but with a modern architecture. Instead of a single shared screen, every session runs independently, connected through a pub/sub message bus. Messages route by channel. Sessions subscribe to the channels they&amp;rsquo;re in. The bus handles delivery.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The SysOp Experience: Building Admin Tools for a Modern BBS</title>
				<link>https://phosphorbbs.net/blog/the-sysop-experience-building-admin-tools-for-a-modern-bbs/</link>
				<pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/the-sysop-experience-building-admin-tools-for-a-modern-bbs/</guid>
				<description>&lt;p&gt;Every BBS needs a sysop. The system operator — the person who manages users, moderates boards, configures channels, and keeps the system running. In the 90s, the sysop sat at the physical machine, running tools from a dedicated admin menu. Today, the sysop connects remotely, just like any other user — but with more power.&lt;/p&gt;&#xA;&lt;p&gt;Phosphor BBS gives the sysop a full terminal-based admin panel. You connect over Telnet or SSH, log in as a sysop-level user, and get access to tools that regular users never see. Everything runs in the terminal — no web dashboard required.&lt;/p&gt;</description>
			</item>
			<item>
				<title>From Modem to SSH: Building a Telnet/SSH Server in Java</title>
				<link>https://phosphorbbs.net/blog/from-modem-to-ssh-building-a-telnet-ssh-server-in-java/</link>
				<pubDate>Thu, 18 Jun 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/from-modem-to-ssh-building-a-telnet-ssh-server-in-java/</guid>
				<description>&lt;p&gt;In the 90s, a BBS was a modem bank and a phone number. Callers dialed in at 2400 baud, negotiated a connection, and got a text interface. The protocol was Telnet — a standard from 1969 that&amp;rsquo;s still surprisingly useful today.&lt;/p&gt;&#xA;&lt;p&gt;But nobody uses modems anymore. Today&amp;rsquo;s BBS callers connect over the internet, either through raw Telnet (port 2323, a nod to the original) or SSH. Building both into a Java BBS means dealing with two completely different networking stacks, terminal negotiation quirks, and a class of bugs that only appear when real clients connect.&lt;/p&gt;</description>
			</item>
			<item>
				<title>jterm: Building a Terminal UI Toolkit in Pure Java</title>
				<link>https://phosphorbbs.net/blog/jterm-building-a-terminal-ui-toolkit-in-pure-java/</link>
				<pubDate>Wed, 17 Jun 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/jterm-building-a-terminal-ui-toolkit-in-pure-java/</guid>
				<description>&lt;p&gt;Every BBS needs a terminal. But not just any terminal — a fast one, with per-character styling, double-buffered rendering, and a widget library that makes building full-screen applications bearable. That&amp;rsquo;s what jterm is: a pure-Java terminal UI toolkit with zero native dependencies.&lt;/p&gt;&#xA;&lt;h3 id=&#34;the-three-layer-architecture&#34;&gt;The Three-Layer Architecture&lt;/h3&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Terminal (raw ANSI/VT100) → Screen (double buffer + diff) → GUI (widgets + layout)&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Each layer has one job:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Terminal&lt;/strong&gt; — raw I/O. Reads keystrokes, writes ANSI escape sequences, handles raw mode and terminal resize events.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Screen&lt;/strong&gt; — double-buffered rendering. Maintains a front buffer (what&amp;rsquo;s on screen) and a back buffer (what&amp;rsquo;s being drawn). On refresh, diffs the two and only sends the changed cells.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;GUI&lt;/strong&gt; — widgets and layout managers. Labels, tables, text boxes, panels, menus. The stuff you actually want to use.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;This separation matters. You can use jterm at any layer — raw terminal access for a door game, screen buffering for a custom renderer, or the full widget library for a typical BBS screen.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Why I&#39;m Building a BBS in 2026</title>
				<link>https://phosphorbbs.net/blog/why-im-building-a-bbs-in-2026/</link>
				<pubDate>Sun, 14 Jun 2026 00:00:00 +0000</pubDate>
				<guid>https://phosphorbbs.net/blog/why-im-building-a-bbs-in-2026/</guid>
				<description>&lt;p&gt;I ran a BBS when I was younger. This was before the web — you&amp;rsquo;d dial in on a modem, read messages, play games, chat with people in your town. It was a community. Then the internet happened, and BBSes faded.&lt;/p&gt;&#xA;&lt;p&gt;But here&amp;rsquo;s the thing: what BBSes did well — community, conversation, shared space — the modern internet does badly. Social media is a firehose of noise. Discord is a walled garden. Slack is for work. Nothing feels like &lt;em&gt;a place&lt;/em&gt; the way a BBS did.&lt;/p&gt;</description>
			</item>
	</channel>
</rss>
