Announcing Rivet: first-party native desktop apps with a Racket core (SwiftUI / WinUI 3 / GTK4)

Hi all — I'd like to introduce Rivet, a framework (MIT, on the package catalog as rivet) for building desktop apps where the application logic is Racket and the UI is each platform's own first-party stack: SwiftUI on macOS, WinUI 3 on Windows, GTK4 on Linux. Its embedding model is inspired by Bogdan Popa's Noise — see "Why not a direct Noise port?" in the docs.

The short version: Rivet embeds the Racket CS runtime inside a real native app process. Your backend declares typed RPCs, events, and shared state; Rivet generates typed Swift / C++ / Kotlin native clients at build time; and the native UI layer stays genuinely native — Rivet is not a WebView framework and not a cross-platform widget toolkit. Each platform keeps its own UI stack and platform behavior.

Hello Rivet

The Racket backend declares the API shared by all three hosts:

#lang racket/base
(require rivet/backend)

(provide start)

(define-event progress)
(define-state counter : Int64 0)

(define-rpc (greet [name : String] : String)
  (format "Hello, ~a!" name))

(define-rpc (increment [value : Int64] : Int64)
  (add1 value))

(define (start in-fd out-fd)
  (serve-fds in-fd out-fd))

raco rivet build reads the RPC / Event / State / Record / Enum schema and generates typed clients — Swift gets increment(value:), C++ gets the native equivalent, Kotlin gets suspend methods. The Racket runtime runs on a dedicated thread inside the app process; native code only ever sees framed messages and generated values, never raw Racket pointers.

What's in the box

  • One backend contract (RPC / Event / State / Cancel) across all three desktop platforms
  • Generated typed native clients (Swift, C++, Kotlin)
  • A real toolchain: raco rivet new / doctor / inspect --json / dev / build / package / verify
  • Agent-native by design: every generated project ships an AGENTS.md and a machine-readable project map, so coding agents can drive the full lifecycle
  • Production packaging: DMG (Developer ID), MSI (Authenticode), deb / rpm / AppImage — plus signed online-update manifests, so apps update themselves safely
  • Real-time chart widgets over one typed data plane, on every host
  • Keel contracts shared with our sibling framework Glaze (the web-UI flavor — separate post on that)
  • Searchable docs: getting started · docs map · Taskboard example app

Is it a demo?

Fair question for any framework announcement, so: Rivet grew under a stack of shipped desktop apps, not the other way around. Everything below is built on it, releases real installers, and several of these self-update in the wild through Rivet's signed update channel — which is the best bug-finder a framework can ask for:

App What it is
Taskly keyboard-first task manager, three platforms
Fulcrum one-keystroke launcher, three platforms
Threadly a native desktop client for this very forum
Payback device cost / payback tracker
PodLens podcast player with transcription & translation
PdfGist local-first PDF reader with AI translation
Movebit work-time tracker & break enforcer tray app
Brainfuel always-on-top quota monitor widget
SyncPilot Resilio Sync companion for Linux
Autarx AUTOSAR integration workbench
Keyward vault for release-signing keys of self-updating apps
gPTP Studio Linux-native gPTP / IEEE 802.1AS debugging workstation (commercial)

(Threadly being a native client for this forum is my favorite proof point — it's dogfooding all the way down.)

Honest scope

  • Three platforms means three native UI codebases. The backend, contract, and generated clients are shared; the UIs are not. That's the trade Rivet makes on purpose — if you'd rather write one HTML UI, that's exactly what Glaze is for.
  • Mobile (iOS / iPadOS / watchOS / Android) has real foundations — typed codecs, generated clients, CI cross-compiles — but finished mobile app delivery is not there yet.
  • You write the native UI in Swift / C++ / Kotlin yourself. Rivet generates the bridging layer, not your views.

Try it

raco pkg install --auto rivet
raco rivet new hello
cd hello && raco rivet dev

raco rivet doctor checks your native toolchain and tells you what's missing in plain language.

Current release: v0.11.0. Feedback, issues, and "why doesn't it do X" are all very welcome — issues or right here in this thread. What would you want from a Racket-native desktop stack?

Good on you for ripping off Noise with AI, I guess.

2 Likes

Hi Bogdan — fair callout, and I should have said this in the announcement itself: Rivet's embedding model is directly inspired by Noise. The credit is in the README ("The embedding model is inspired by Noise…"), and docs/architecture.md has a section — "Why not a direct Noise port?" — on what we kept and where Rivet diverges. But this thread is where most people meet the project first, so that's where the credit belonged.

The longer version of the credit: your open-source work is a big part of why I'm building in Racket at all. koyo showed me what a production-grade Racket project can look like, your blog posts made so much of the ecosystem legible, and Noise proved the embedding approach Rivet stands on — Racket CS inside a native app process, with the UI staying fully native behind a message boundary. Rivet's part is making that contract platform-neutral from day one: Swift and C++ as peer clients over one typed protocol, plus the lifecycle, packaging, and signed-update tooling around it, rather than a Swift-first core translated to other platforms later.

However the code gets written, the ideas we build on are ours to credit — so: thank you. Giving something back to the Racket community is exactly what all of this is for, and if you ever take Rivet for a spin, honest feedback would mean a lot.

@turinglambdaai ... you sound a lot like AI. Just saying? I'm not really convinced that you're human. Wow. It's a weird world we live in.

1 Like

(In addition to the more fundamental critiques already made:)

I would suggest that this is not a useful description. I am not aware of any GUI solution in Racket that is a “cross-platform widget toolkit.”

In particular, racket/gui does not work that way. For example, a Racket button% is implemented by a native GtkButton, NSButton, or a Win32 BUTTON.

(Technically, it is possible to specially configure Racket to use GTK on Mac OS and even Windows, but this is not the default or a common configuration. Historically, PLT Scheme used wxWidgets—which is closer to being a “cross-platform widget toolkit,” but still not in the sense of e.g. Qt—but that has not been the case at least since the port of racket/gui from C++ to Racket in Racket 5.1 (February 2011), and I think wxWidgets may have been replaced even earlier.)