Projects / Delta Chat Desktop

Delta Chat Desktop

TypeScriptElectronReact
Screenshot of Delta Chat Desktop showing a group chat

About this project

Delta Chat is a decentralized, encrypted messenger that works over standard email. The desktop client is an Electron/React app that ships to Windows, macOS, and Linux (including Flathub, the Mac App Store, and the Microsoft Store).

I joined the small desktop team (2-5 people over the years) at the end of 2018. Over the years I took on more responsibility and became the de facto lead - first sharing the role with jikstra, then carrying it alone after he left the desktop team in 2022. In spring 2024, Nico began taking over, and we completed the transition in 2025. My last major initiative was the DeltaTauri project - an NLnet-funded prototype porting the app from Electron to Tauri.

Technical challenges

Taming the binding layers

The original architecture had too many layers: a C core library, wrapped via NAPI bindings, wrapped again in a JS module, called from Electron's main process, which forwarded everything to the renderer. Every method was redefined at each layer. Worse, we couldn't get the C core to link on Windows at all, which blocked the app from shipping there.

The C core was eventually rewritten in Rust (via c2rust1, then 1.5 years of manual cleanup), which solved the Windows problem instantly - Rust's tooling handles cross-compilation far better. But the layered NAPI/CFFI bindings and their repetition remained. I eventually introduced a JSON-RPC API with auto-generated TypeScript bindings - define once in Rust, use directly in TypeScript. Later, during the DeltaTauri project, we replaced the NAPI layer entirely with a stdio-based RPC binary2 - until then, the JSON-RPC API had still been going through the old CFFI layer. I wrote a blog post about the journey.

Message list and chat list performance

Getting the message list fast and bug-free took multiple attempts. Virtualization libraries at the time didn't support dynamic-height items when scrolling from the bottom up (which is how chat apps work), so we used a pagination approach instead. But treating messages as discrete pages introduced its own bugs: pages not loading, duplicate messages appearing, state not updating on deletion. We eventually kept the batch-loading mechanism but dropped the page abstraction, treating everything as a single flat list. Later, WofWca did a deep dive into the remaining edge cases and fixed many subtle bugs.

Webxdc sandboxing

Delta Chat supports webxdc mini apps - small web apps that run inside the messenger with no internet access. Figuring out how to properly sandbox untrusted user-generated content inside Electron was a significant challenge. This work later carried over into the DeltaTauri project, where Tauri's capability-based permission system offered a more natural fit for the sandboxing model.

Supply chain awareness

We deliberately kept the dependency count low. This was a general principle, but became very real when a dependency of our testing framework (TestCafe) was sabotaged by its own maintainer at the start of the Ukraine war: the code wiped files on systems it geolocated to Russia and dropped a protest message on everyone else's. One day I found a be glad that you are not russian text file sitting on my desktop. We eventually moved away from TestCafe entirely.

Architecture decisions

I pushed hard for adopting TypeScript and later for enabling strict mode (noImplicitAny and strictNullChecks). This paid off enormously as the codebase grew. I also drove the shift from the layered NAPI binding architecture to the JSON-RPC API, which was one of the most impactful changes - it simplified the codebase and made it possible to support new frontends without writing new bindings.

Distribution and releases

Shipping to the Mac App Store, Microsoft Store, and Flathub meant dealing with review cycles, expiring certificates, and platform-specific build quirks. Flathub requires fully offline builds on their runners, which caused many headaches - iteration cycles are slow3, and you need to understand their build system. On the upside, the Flathub maintainers are very helpful when you ask.

We invested heavily in automating the release process, but it still required manual intervention: test releases, last-minute bug fixes, deciding which PRs go into the release window, and communicating with testers. We held a high standard for releases, which meant the process was never fully hands-off.

What I learned

This was my first project working in an actual team of developers, and it taught me a lot beyond just code. React, Rust, different bundlers and build tools, issue gardening, how to work with people across time zones and circadian rhythms4, and how to maintain a long-running open-source project without burning out - though I didn't always succeed at that last one. I was also active across the broader Delta Chat ecosystem (community forum, webxdc, bots, chatmail), which was rewarding but at times simply too much.


  1. c2rust is an automated C-to-Rust transpiler. It produces working but unidiomatic Rust code that then needs manual cleanup.
  2. This applies to the Electron version. The Tauri edition includes the Rust core directly, since Tauri is also Rust.
  3. You can run flatpak-builder locally, and I did eventually, but iteration is still slow - you need a fast Linux machine, since the tool isn't made for macOS.
  4. I was a night owl myself for quite some time, especially in the earlier days.