DEV Community

木头人
木头人

Posted on

Why I Abandoned Electron & SPAs to Build a 128MB Local-First Desktop AI Agent

How the ERTH Architecture (ElectroBun + Robyn + Turso + HTMX) breaks the obesity of modern desktop app development.


If you’ve tried to build a cross-platform desktop application recently, you’ve likely faced the classic developer’s dilemma:

  1. Electron makes developer velocity fast, but at the cost of dragging a bloated Chromium kernel and Node.js runtime into every build. A simple "Hello World" easily eats up 200MB+ of disk space and hundreds of megabytes of RAM.
  2. Tauri solves the footprint issue by using OS-native WebViews and Rust, but forces you onto Rust’s steep learning curve, sacrificing the agility of rapid prototyping.
  3. The Python Distribution Hell: With the rise of local LLMs and Edge AI, Python is the de facto language for AI orchestration. Yet, packaging Python, its heavy dependencies, and databases into a double-click-to-run package for non-technical users remains a nightmare.

Faced with these shackles, I decided to take a step back and rewrite the physical laws of desktop development.

Today, I’m introducing the ERTH Stack (ElectroBun + Robyn + Turso + HTMX)—a heterogeneous, local-first, zero-JS desktop application architecture designed for independent full-stack creators.

And yes, the entire bundle—including a browser shell, a high-performance Python sidecar, a local database, and local AI agent execution—packages into a single 128MB standalone binary.

Our open-source implementation is live on GitHub:

👉 GitHub Repository: bnpysse/erth_assistant


The Core Pillars of the ERTH Architecture

To achieve a minimalist footprint without sacrificing developer velocity, we structured the architecture into four core layers:

              ERTH ARCHITECTURE
  [E]lectroBun (UI Shell) ───[HTMX]───► [H]TMX (Zero-JS Frontend)
        │                                    ▲
      (IPC)                               (HTTP)
        ▼                                    │
  [R]obyn (Python Sidecar) ───────────► [T]urso / libSQL (Local-First DB)
Enter fullscreen mode Exit fullscreen mode

1. [E]lectroBun: The Lightweight Shell

Instead of Electron’s heavy Chromium, ElectroBun binds directly to the OS-native WebKit engine (Cocoa WebKit on macOS, WebView2 on Windows). The main process runs on Bun, launching in milliseconds and keeping idle memory consumption incredibly low.

2. [R]obyn: The Rust-Powered Python Sidecar

Python handles the heavy lifting—AI logic, local LLM mounting, and database orchestration. We use Robyn, a high-performance, async Python web framework built on a Rust runtime. It runs as a background sidecar process, dynamically spawned by the Bun main process on Port 0 to avoid port collision conflicts.

3. [T]urso: Local-First with Cloud-Edge Sync

We use libSQL (Turso). The database is a physical file residing locally (local_edge.db), executing CRUD operations at a blinding 0.1ms latency. Meanwhile, a silent background thread replicates incremental changes to the Turso cloud database, providing seamless offline immunity.

4. [H]TMX: Hypermedia-Driven UI

We threw client-side SPAs (React/Vue) and Webpack/Vite pipelines out of the window. By introducing HTMX, our frontend behaves as a lightweight hypermedia receiver. The Robyn Python backend renders HTML fragments directly, and HTMX swaps them into the DOM out-of-band (OOB Swap). Zero client-side JS business logic, zero state-sync headaches.


Surviving the Deep-Water Debugging Zone

Building a heterogeneous cross-language desktop app is not without its traps. During development, we had to solve three major technical challenges:

  • Watchdog Self-Healing Pipeline: Since the app runs a Bun main process and a Python sidecar, what happens if the Python backend crashes? We built a watchdog monitoring pipeline that probes the backend every 3 seconds. If the backend dies, the watchdog executes a silent SIGTERM restart and re-negotiates a new dynamic port seamlessly.
  • CORS & OPTIONS Preflight Trap: Since HTMX sends cross-origin requests with custom headers (hx-request, hx-target), browsers trigger automatic OPTIONS preflight checks. In Robyn’s Rust-based core, we had to ensure preflight requests bypass the auth middleware to prevent socket deadlocks.
  • Opaque Token Interception: To prevent other local programs from scanning ports and hijacking our Python backend, communication is locked down with UUIDv7 short-lived tokens (Opaque Tokens) injected during startup.

Read the Full Engineering Blueprint

I have documented the entire process—from setting up the dual-core ignition, building the self-healing watchdog, writing Cocoa NSPanel window float hooks, to building cross-platform GitHub Actions pipelines—in my new book:

📖 "ERTH Assistant: Local-First + AI Sidecar Desktop Architecture"

If you want to build high-performance, secure desktop AI assistants, you can get the book on Leanpub.

I have also made a Free 5-Chapter Preview Edition available for download directly on the landing page!

  • Let me know what you think of the ERTH stack in the comments. Let's reclaim local computing sovereignty together!

Top comments (0)