<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Open Source on Phosphor BBS</title>
		<link>https://phosphorbbs.net/tags/open-source/</link>
		<description>Recent content in Open Source 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/tags/open-source/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>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 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>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>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>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>
	</channel>
</rss>
