Skip to main content

Saimin 2 Chat System

Laurence A. Lee
Author
Laurence A. Lee
Aloha! I’m Laurence — Enterprise Architect and Cloud Platform Engineer, Honolulu-based, currently consulting via Lalee Innovations.
Table of Contents

What It Is
#

Saimin 2 is a browser-based recreation of Saimin Chat System — a real multi-user BBS that ran on an Apple II+ in Aiea, Hawaii in the 1980s and early 1990s. Five phone lines, 300 baud, a small community of regulars who dialed in to chat in real time.

The recreation preserves the original user experience exactly: a character-mode terminal in the browser, 15 numbered lines, the same community moderation mechanics, the same time-allocation model, and the same welcome screen. When the lines are full, you get a system-busy message. That is the entire feature set, by design.

Site: saimin2.com

Stack
#

Frontend: xterm.js in the browser over a WebSocket connection. VT100/ANSI character-mode terminal rendering. No web framework, no SPA — the interface is the terminal.

Backend: Python 3.12 and FastAPI with native asyncio WebSocket support. All 15 connections are managed by a single in-process event loop. Ephemeral session state — line assignments, session handles, strike counts, authentication flags — lives in process memory and resets on restart, preserving the original BBS behavior.

Data: SQLite in WAL mode via aiosqlite, managed with Alembic migrations. The entire persistent dataset — member records, time balance ledger, message boards, audit log — is a single file on a PersistentVolumeClaim.

Billing: Stripe Checkout for membership subscriptions. Card data never contacts BBS infrastructure. Webhooks trigger member provisioning and status updates.

Deployment: Single Kubernetes pod with a PersistentVolumeClaim for the SQLite file. Monthly time-credit allocation runs as a Kubernetes CronJob.

BROWSER — Caller's device
xterm.js — VT100/ANSI terminal
Character-mode rendering
WebSocket client
↕  WebSocket (full-duplex, persistent)
FASTAPI APPLICATION — Single asyncio process, 15 concurrent connections
asyncio event loop
Session registry (in-memory)
BBS command processor
Chat fan-out (in-process)
Stripe webhook handler
↕  aiosqlite  |  Stripe API
PERSISTENCE — SQLite WAL, single file on PersistentVolumeClaim
Member records
Time balance ledger
Message boards
Audit log
Alembic migrations
↕  Stripe Checkout (redirect)  |  Stripe Webhooks (inbound)
EXTERNAL SERVICES
Stripe — membership billing
Kubernetes CronJob — monthly credit allocation

Notable Decisions
#

SQLite over PostgreSQL (ADR-012): The original Saimin ran on a single machine with a floppy disk as its store. An embedded SQLite file is closer to that model and eliminates an entire infrastructure component. The WAL mode write throughput is adequate for 15 concurrent users; the Alembic migration path handles schema evolution. An earlier PostgreSQL deployment was replaced by ADR-012.

Single-process asyncio, no external message broker: Chat fan-out is handled entirely in-process. At 15 connections, the complexity of Redis pub/sub or a message queue produces no benefit and considerable operational cost. The design ceiling is explicit — this system is not built to scale beyond 15 lines — so the architecture reflects that constraint rather than hedging against it.

No web framework on the frontend: The client is xterm.js wired to a WebSocket. No React, no SPA, no client-side routing. The interface is the terminal; that is the product.

🌐 Client Browser
──→
KUBERNETES CLUSTER
Ingress
FastAPI Pod
SQLite PVC
CronJob — 1st of month
──→
monthly time-credit allocation
Stripe
──→ webhooks ──→
FastAPI Pod (membership provisioning)

Enterprise Architecture Methodology
#

The project is unusual in that the entire architecture was designed before any application code was written.

The governance framework includes:

  • TOGAF 10 methodology (adapted for project scale, not strict compliance)
  • Architecture Review Board with formal ADR (Architecture Decision Record) process — 12 ADRs ratified as of the architecture phase
  • Business capability model — 19 capability domains across four BIAN-inspired tiers
  • Full requirements documentation — Business Requirements Document, Functional Requirements Specification, Non-Functional Requirements, and UAT Protocol
  • Traceability matrix linking business objectives through requirements to capabilities and ADRs
  • EA Landscape Register and formal project engagement model
The Scale
15 numbered lines
99 members maximum
1 FastAPI process
1 SQLite file
1 Kubernetes pod
0 external message brokers
The Discipline
TOGAF 10 governance framework
Architecture Review Board
12 ratified Architecture Decision Records
19-capability BIAN-inspired model, 4 tiers
Full BRD · FRS · NFR documentation
Traceability matrix · UAT protocol

The architecture documentation is published openly on saimin2.com. This makes the project interesting in two directions: as a faithful BBS recreation, and as a live example of what formal EA governance looks like applied at community scale.

Community Governance
#

Saimin 2 is designed to be self-governing. The ARB is in bootstrap configuration during build. As the system moves to live operation and a member community forms, governance is intended to transition to member voting — on architecture direction, features, and community rules — replicating how the original Saimin community governed itself. The governance framework was designed with that transition in mind from the start.

Membership fees cover hosting costs. Any surplus at year end is donated to charity.

Related

Mobile Concierge - WBIDA

What It Was # The WBIDA Mobile Concierge was an internal field operations application built for the Waikiki Business Improvement District Association — the organization responsible for managing and maintaining the Waikiki commercial district in Honolulu. The app was used by WBIDA’s Aloha Ambassadors, the district’s uniformed street-level field staff, as their primary tool for logging activity and reporting issues across the district.