README.md

# Plushie for Gleam

Build native desktop apps in Gleam. **[Pre-1.0](#status)**

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](https://github.com/iced-rs/iced), a cross-platform GUI library
for Rust, which plushie drives as a precompiled binary behind the scenes.

<!-- test: readme_counter_init_test, readme_counter_view_structure_test -- keep this code block in sync with the test -->
```gleam
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())
}
```

```bash
gleam run -m examples/counter
```

This is one of [8 examples](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:

```sh
gleam add plushie_gleam
```

Then:

```bash
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](CHANGELOG.md) carefully when upgrading.

The precompiled binary requires no Rust toolchain. To build from
source instead, install [rustup](https://rustup.rs/) and run
`gleam run -m plushie/build`. See the
[getting started guide](docs/getting-started.md) for the full
walkthrough.

## Features

- **38 built-in widget types** -- buttons, text inputs, sliders,
  tables, markdown, canvas, and more. Easy to build your own.
  [Layout guide](docs/layout.md)
- **22 built-in themes** -- light, dark, dracula, nord, solarized,
  gruvbox, catppuccin, tokyo night, kanagawa, and more. Custom
  palettes and per-widget style overrides.
  [Theming guide](docs/theming.md)
- **Multi-window** -- declare window nodes in your widget tree;
  the framework opens, closes, and manages them automatically.
  [App behaviour guide](docs/app-behaviour.md)
- **Platform effects** -- native file dialogs, clipboard, OS
  notifications. [Effects guide](docs/effects.md)
- **Accessibility** -- screen reader support via
  [accesskit](https://accesskit.dev) on all platforms.
  [Accessibility guide](docs/accessibility.md)
- **Live reload** -- edit code, see changes instantly. Enabled by
  default in dev mode.
- **Extensions** -- multiple paths to custom widgets:
  - **Compose** existing widgets into higher-level components with
    pure Gleam. No Rust, no binary rebuild.
  - **Draw** on the canvas with shape primitives for charts, gauges,
    diagrams, and other custom 2D rendering.
  - **Native** -- implement `WidgetExtension` in Rust for full
    control over rendering, state, and event handling.
  - [Extensions guide](docs/extensions.md)
- **Remote rendering** -- native desktop UI for apps running on
  servers or embedded devices. Dashboards, admin tools, IoT
  diagnostics -- over SSH with configurable event throttling.
  [Running guide](docs/running.md)

## Testing

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

- **Mocked** -- millisecond tests, no display server. Uses a shared
  mock process for fast logic and interaction testing.
- **Headless** -- real rendering via
  [tiny-skia](https://github.com/linebender/tiny-skia), no display
  server needed. Supports screenshots for pixel regression in CI.
- **Windowed** -- real windows with GPU rendering. Platform effects,
  real input, the works.

```gleam
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](docs/testing.md) for the full API, backend
details, and CI configuration.

## How it works

Under the hood, a renderer built on
[iced](https://github.com/iced-rs/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](docs/extensions.md) 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](docs/running.md) 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:

- Pin to an exact version and read the
  [CHANGELOG](CHANGELOG.md) when upgrading.
- The extension framework (`plushie/extension`) is the least stable
  part of the API.

## Documentation

Guides are in [`docs/`](docs/) and will be on
[hexdocs](https://hexdocs.pm/plushie_gleam) once published:

- [Getting started](docs/getting-started.md) -- setup, first app, CLI helpers, dev mode
- [Tutorial](docs/tutorial.md) -- build a todo app step by step
- [App behaviour](docs/app-behaviour.md) -- the Gleam API contract, multi-window
- [Layout](docs/layout.md) -- length, padding, alignment, spacing
- [Events](docs/events.md) -- full event taxonomy
- [Commands and subscriptions](docs/commands.md) -- async work, timers, widget ops
- [Effects](docs/effects.md) -- native platform features
- [Theming](docs/theming.md) -- themes, custom palettes, styling
- [Composition patterns](docs/composition-patterns.md) -- tabs, sidebars, modals, cards, state helpers
- [Scoped IDs](docs/scoped-ids.md) -- hierarchical ID namespacing
- [Testing](docs/testing.md) -- three-backend test framework and pixel regression
- [Accessibility](docs/accessibility.md) -- accesskit integration, a11y props
- [Extensions](docs/extensions.md) -- custom widgets, publishing packages

## Development

```bash
./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](https://rustup.rs/) and the platform-specific libraries:

- **Linux (Debian/Ubuntu):**
  `sudo apt-get install libxkbcommon-dev libwayland-dev libx11-dev cmake fontconfig pkg-config`
- **Linux (Arch):**
  `sudo pacman -S libxkbcommon wayland libx11 cmake fontconfig pkgconf`
- **macOS:** `xcode-select --install`
- **Windows:**
  [Visual Studio Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/)
  with "Desktop development with C++"

## Links

| | |
|---|---|
| Gleam SDK | [github.com/plushie-ui/plushie-gleam](https://github.com/plushie-ui/plushie-gleam) |
| Elixir SDK | [github.com/plushie-ui/plushie-elixir](https://github.com/plushie-ui/plushie-elixir) |
| Renderer | [github.com/plushie-ui/plushie](https://github.com/plushie-ui/plushie) |
| Rust crate | [crates.io/crates/plushie](https://crates.io/crates/plushie) |

## License

MIT