Gleam + Relm4 foreign node POC over Erlang distribution
gleamtk#
Proof of concept: a Relm4 (GTK4 / libadwaita) process that acts as an Erlang foreign node, controlled by a Gleam process over the Erlang distribution protocol.
Gleam (beam) ── cookie + epmd ──► Relm4 foreign node (Rust)
gleamtk@127.0.0.1 ui@127.0.0.1
controller ── {gui, Node} ! ──► registered name: gui
◄── events ── {controller, …} ── clicks / ready / pong
Protocol#
Gleam → UI ({gui, 'ui@127.0.0.1'} ! Term):
| Term | Effect |
|---|---|
hello |
Handshake; UI records controller pid |
{set_title, Binary} |
Window title |
{set_label, Binary} |
Main label |
{set_count, Int} |
Counter display |
ping |
UI replies pong |
UI → Gleam (to registered controller or the sender pid):
| Term | Meaning |
|---|---|
{ready, <<"ui@…">>} |
UI node is up |
{clicked, Count} |
Primary button |
{count_changed, Count} |
− button |
pong |
Reply to ping |
window_closed |
Window closed |
Requirements#
- Nix (recommended) or: Erlang/OTP, Gleam, Rust, GTK4, libadwaita, epmd
- A display (Wayland/X11) for the Relm4 window
Run#
cd gleamtk
nix develop # or: nix develop -c bash
just run # starts UI then Gleam controller
Two terminals:
# terminal 1
just ui
# terminal 2
just gleam
Click Click me / + in the window. Gleam prints events and updates the label and count over distribution.
Layout#
gleamtk/
gleam/ # Gleam controller (BEAM node)
ui/ # Relm4 + erl_dist foreign node
justfile
flake.nix
Notes#
- Cookie defaults to
gleamtk; both sides must match. - Long node names on
127.0.0.1avoid short-name / hostname mismatches. - The Rust side uses
erl_dist; the UI thread never blocks on distribution I/O. - This is a POC, not a full widget toolkit binding.