Plushie for Gleam

Build native desktop apps in Gleam. Pre-1.0

Plushie is a desktop GUI framework that allows you to write your entire application in Gleam – state, events, UI – and get native windows on Linux, macOS, and Windows. Rendering is powered by iced, a cross-platform GUI library for Rust, which plushie drives as a precompiled binary behind the scenes.

import gleam/int
import plushie/app
import plushie/gui
import plushie/command
import plushie/event.{type Event, WidgetClick}
import plushie/node.{type Node}
import plushie/prop/padding
import plushie/ui

type Model {
  Model(count: Int)
}

fn init() {
  #(Model(count: 0), command.none())
}

fn update(model: Model, event: Event) {
  case event {
    WidgetClick(id: "inc", ..) -> #(Model(count: model.count + 1), command.none())
    WidgetClick(id: "dec", ..) -> #(Model(count: model.count - 1), command.none())
    _ -> #(model, command.none())
  }
}

fn view(model: Model) -> Node {
  ui.window("main", [ui.title("Counter")], [
    ui.column("content", [ui.padding(padding.all(16.0)), ui.spacing(8)], [
      ui.text_("count", "Count: " <> int.to_string(model.count)),
      ui.row("buttons", [ui.spacing(8)], [
        ui.button_("inc", "+"),
        ui.button_("dec", "-"),
      ]),
    ]),
  ])
}

pub fn main() {
  gui.run(app.simple(init, update, view), gui.default_opts())
}
gleam run -m examples/counter

This is one of 8 examples included in the repo, from a minimal counter to a full widget catalog. Edit them while the GUI is running and see changes instantly.

Getting started

Add plushie to your dependencies:

gleam add plushie_gleam

Then:

gleam run -m plushie/download         # download precompiled binary
gleam run -m my_app                   # run your app

Pin to an exact version and read the CHANGELOG carefully when upgrading.

The precompiled binary requires no Rust toolchain. To build from source instead, install rustup and run gleam run -m plushie/build. See the getting started guide for the full walkthrough.

Features

Testing

Plushie ships a test framework with three interchangeable backends. Write your tests once, run them at whatever fidelity you need:

import gleeunit/should
import gleam/option
import plushie/testing as test
import plushie/testing/element

pub fn add_and_complete_a_todo_test() {
  let session = test.start(todo_app)
  let session = test.type_text(session, "new_todo", "Buy milk")
  let session = test.submit(session, "new_todo")

  let assert option.Some(el) = test.find(session, "todo_count")
  let assert option.Some(txt) = element.text(el)
  should.equal(txt, "1 item")
  should.be_true(option.is_some(test.find(session, "todo:1")))

  let session = test.toggle(session, "todo:1")
  let session = test.click(session, "filter_completed")

  let assert option.Some(el) = test.find(session, "todo_count")
  let assert option.Some(txt) = element.text(el)
  should.equal(txt, "0 items")
  should.be_true(option.is_none(test.find(session, "todo:1")))
}

See the testing guide for the full API, backend details, and CI configuration.

How it works

Under the hood, a renderer built on iced handles window drawing and platform integration. Your Gleam code sends widget trees to the renderer over stdin; the renderer draws native windows and sends user events back over stdout.

You don’t need Rust to use plushie. The renderer is a precompiled binary, similar to how your app talks to a database without you writing C. If you ever need custom native rendering, the extension system lets you write Rust for just those parts.

The same protocol works over a local pipe, an SSH connection, or any bidirectional byte stream – your code doesn’t need to change. See the running guide for deployment options.

Status

Pre-1.0. The core works – 38 widget types, event system, 22 themes, multi-window, testing framework, accessibility – but the API is still evolving:

Documentation

Guides are in docs/ and will be on hexdocs once published:

Development

./bin/preflight                       # run all CI checks locally

Mirrors CI and stops on first failure: format, compile, test.

System requirements

The precompiled binary (gleam run -m plushie/download) has no additional dependencies. To build from source, install a Rust toolchain via rustup and the platform-specific libraries:

Links

Gleam SDKgithub.com/plushie-ui/plushie-gleam
Elixir SDKgithub.com/plushie-ui/plushie-elixir
Renderergithub.com/plushie-ui/plushie
Rust cratecrates.io/crates/plushie

License

MIT

Search Document