Server-Backed Backends and Peripherals Go Physical
Migrating backends to server APIs with NATS pub/sub, adding microservices, and building the peripheral slot system alongside the Canada Goose game.
On this page
The emulator has been a browser island: fast to ship, easy to iterate, allergic to persistence. That shape stops working the moment you need shared state, moderation, or anything that outlives a tab. Today I cut over to a real backend: three gRPC services, a WebSocket gateway, and NATS for real-time events.
Backends Become Services
Three gRPC services now own the heavy data paths:
users-serviceon port50051for profiles, presence, and account settings.messaging-serviceon port50052for BBS, Usenet, and email.market-serviceon port50053for quotes, portfolios, and trades.
Each service lives in its own Rust crate with its own tables, and each talks to a Redis-compatible cache (Dragonfly) for hot reads. The WebSocket gateway is the single entry point; it routes requests into the correct service and emits real-time events over NATS so other connected clients can react.
The gateway doesn’t implement business logic; it forwards and emits. That keeps failures local to whichever service caused them.
Quotes: Finnhub With A Fallback
The stock ticker backend now uses Finnhub instead of Yahoo. Yahoo’s cookie and crumb flow was brittle enough that I was spending my time on auth rather than market logic. Finnhub is predictable: one request per symbol, then a five‑minute sleep.
When the API fails or the key is missing, the ticker falls back to a random‑walk simulation, so the UI keeps moving even when the world goes quiet.
Flow Control Stops Dropping Bytes
The server move surfaced a serial problem I’d been living around: large payloads over slow links overrun the modem buffer if you don’t respect CTS. That’s a correctness issue, not a performance one. When CTS drops, output queues; when it rises, output drains. With that enforced, the “missing welcome screen” bug disappeared.
Peripherals Grow A Physical Layer
The other thread today is visual. A peripheral should feel like a piece of hardware rather than a menu entry, which means a fixed place, a consistent affordance, and a face you can zoom into.
I built a slot system and a modal viewer that scales from the slot’s position. The modal’s transform‑origin is computed from the source element’s bounding box, so it reads as pulling a device forward from the chassis instead of opening a new page. The peripheral manager owns the mapping from device IDs to Lit component tags and lazy‑creates the full view on first zoom.
Slot → device → view. Naming it that way made the rest of the work mechanical.
Canada Goose And DATAPAC
Two new backends:
- Canada Goose Simulator: a text adventure with a day‑night loop, multiple victory conditions, and an audio generator that produces honks, flaps, and splashes. It’s also a good stress test for the serial UI stack, since it emits both dense text and short prompts.
- DATAPAC X.25: a simulator for Canada’s packet network, which opened in 1977 and was finally shut down at the end of 2009, including PAD command mode and virtual host routing.
Both are weird by design. The project is more interesting when the platform can host sensible tools and niche history side by side.
OAuth Handle Selection
OAuth users now choose their own handle instead of inheriting an auto‑generated one. The rules: 3–16 characters, ASCII letters, numbers and underscores only, no GUEST_ prefix. The availability check runs before the account is created, so the pending OAuth token stays valid if the first choice is taken.
That ordering is the difference between a retryable form and a support ticket.
What Changed
- Migrated multiple backends behind the gateway and split them into
users-service,messaging-service, andmarket-service. - Added NATS for real‑time events and Redis/Dragonfly for shared caching.
- Switched stock quotes to Finnhub with a random‑walk fallback.
- Shipped the peripheral slot + modal system with scale‑from‑source animation.
- Added Canada Goose Simulator and DATAPAC X.25 backends.
- Implemented OAuth handle selection with strict validation rules.
What’s Next
Tomorrow: SignalBus subscriptions across the peripheral slots — floppy, cassette, hard drive, CD-ROM — so they can react to system state. The slot views exist; right now they’re inert.
Previous: 2026-01-31