Over the years I’ve tried a variety of client architectures, ranging from thick clients using MFC or wxWidgets, pure client-side multi-page apps, server-side rendered PHP or Python/Django, single page applications (SPAs) using Angular or React. You name it, I’ve tried it.

As for my favorite architecture, because it was the most flexible, back in 1988 I designed a system that used CICS with ASM and Cobol server side rendered pages, mixed with the Borland Grapics Library and Turbo C 2.0. This mixture dramatically improved rendering speed thanks to the way the massive IBM mainframe prioritized CICS execution over batch jobs, and improved UX thanks to the partially thick client.

The modern equivalent to this is React, Typescript, flex-layout, and react-flow combined with dynamic menus, htmx, and a-h/templ server-side rendered pages.

State, access controls, input validation, page layout, etc is handled once and only once on the server, eliminating the need for dual implementation typically seen in traditional web applications, while still having the quick response times.

Taking this even further, and abandoning the issues of using Electron, my Correct Architecture uses Wails for the local-first implementation. If you’ve ever complained about MS Teams not being capable of viewing multiple accounts simultaneously, you know a bit about what I’m taking about. Go Wails doesn’t suffer this problem, takes significantly less memory, smaller downloads, and uses Go, which allows for much more common code without requiring the IPC mechanism of Electron.

One language, one shared code base for web apps, local thick apps, mobile apps, and hybrid thick client apps with a hosted backend.

Also, since NATS can run embedded in the Go application, as can LanceDB and SQLite, there’s no need for separate processes, containers, or network ports for these when running a single local-first binary. Personal data remains 100% local, and sovereign enterprise data remains within the enterprise network.

Third-party modules can run locally in LXD containers on most modern desktops and laptops, or remotely using the same LXD centered implementation. Enterprise Sovereignty is maintained while personal data is kept locally.

Traditionally these third-party modules needed to be bundled with the main application, or use tricks with iframes, executing untrusted Javascript directly in the client browser, or requiring external APIs and webhooks that can expose sensitive data to third party vendors.

Running these modules within LXD containers, isolating via firewall rules prevents leakage. The modules only have access to data and resources explicitly granted. Rendering on the server and using htmx on the client and restricting third party client code reduces the attack footprint, and additional security measures provided by Wails closed the gap entirely.

Concrete UI Composition (flex-layout + react-flow)

​So, what does this actually look like when you sit down to use the workspace shell?

​Instead of a rigid, static web dashboard or a bloated single-page app trying to do everything at once, you get a clean, highly responsive layout that feels like a professional IDE. We use flex-layout to manage the multi-tab, customizable dockable panes. You can drag, split, resize, and stack views however your workflow demands, without the UI breaking or lagging.

​Inside those panes, react-flow powers a visual node-graph canvas. This is where the magic of server-side rendering really shines. Instead of writing complex client-side JavaScript components for every node type, Go-rendered SSR components stream dynamically straight from the backend into these visual nodes. You can visually plug data pipelines, AI models, and custom business logic together into live workflows, while the actual execution state remains strictly governed on the server side. You get the fluid visual feel of a modern node-based canvas, backed by the raw speed and safety of compiled Go templates (a-h/templ) and htmx.

​The Architectural Payoff

​When you step back and look at the whole picture, this client architecture solves the fundamental trade-off that has plagued software engineering for decades: choosing between desktop responsiveness and web maintainability.

​By unifying state, authorization, and rendering logic on the server, we eliminate the nightmare of maintaining duplicate implementations on both sides of the network boundary. At the same time, leveraging native Go execution via Wails gives you the instant startup, low memory footprint, and tight hardware integration of a true desktop application. You aren’t giving up performance for convenience, nor are you giving up enterprise control for desktop speed.

​Returning to First Principles

​After nearly forty years of watching desktop, web, and cloud frameworks repeatedly bloat, collapse, and reinvent themselves under new buzzwords, you learn to spot true efficiency. Returning to a single-source, hypermedia-driven rendering model paired with a lightweight native runtime isn’t nostalgia. It’s the result of stripping away decades of unnecessary abstraction until only what actually works remains. It is, simply put, the correct answer.

​If you’re finding this deep dive into clean-room system design valuable, subscribe to my Substack and tell me what you think.

I’ll be releasing regular technical breakdowns, architecture benchmarks, and open-source code as I continue building out the platform, including upcoming posts on the native runtime and my unique multi-axis memory engine.