Roxane
A pure-Ruby desktop shell: a native window over the operating system's webview (WebView2 / WKWebView / WebKitGTK, via the webview C library), with a Ruby⇄JS operation bridge. A lightweight, Tauri-shaped way to ship a web frontend as a desktop app — in Ruby.
Named for Cyrano's Roxane.
What it is (and isn't)
Roxane is the host and data plane — a window, the system webview, an
invoke/emit bridge, and a loopback asset server. It serves whatever frontend
you give it and is agnostic to look-and-feel (no CSS, no widgets, no layout
opinions). The same frontend can run in the desktop shell and in a hosted browser.
Example
require "roxane"
win = Roxane::Window.new(title: "Hello", size: [900, 600])
# JS → Ruby: await window.roxane.invoke("greet", "world")
win.on("greet") { |name| "Hello, #{name}!" }
# Ruby → JS: window.roxane.on("tick", ({ at }) => ...)
win.emit("tick", { at: Time.now.to_i })
win.serve(File.("ui")) # serve a built frontend bundle, or:
# win.load("http://localhost:5173") # point at a dev server, or:
# win.html("<!doctype html>…") # inline HTML
win.run
Invocation handlers run off the UI thread, and emit/eval are safe from any
thread — so long-running work (e.g. an AI call) never freezes the window.
Requirements
The webview C library (libwebview) must be available at runtime. The
precompiled platform gem (e.g. x86_64-linux) vendors it, so you only need
the system webview runtime (WebKitGTK on Linux). Otherwise set ROXANE_LIBWEBVIEW
to a libwebview path, or have it on the loader path.
Packaging (precompiled platform gems)
Roxane ships a prebuilt libwebview per platform (the nokogiri model) so users
need no toolchain. For x86_64-linux:
rake vendor:linux # build libwebview into vendor/x86_64-linux/
rake gem:linux # build roxane-<ver>-x86_64-linux.gem (vendoring the lib)
rake verify:linux # install that gem in a clean container and smoke-test it
macOS / Windows / aarch64 cross-builds are next.
Testing
./run.sh # Docker: Ruby + libwebview + headless Xvfb → full suite
rake test # host: unit tests only (the asset server); the windowed
# smoke test self-skips unless ROXANE_INTEGRATION=1
Linux / Wayland note (window size)
On GTK3, upstream libwebview implements WEBVIEW_HINT_NONE with
gtk_window_resize. Under Wayland that does not set the initial xdg
geometry, so floating compositors (e.g. Hyprland) often map the window at a
tiny 200×200 square; GNOME hides the same bug. Roxane compensates on Linux by
calling gtk_window_set_default_size and briefly pinning a size-request through
first map (then releasing it so the window stays resizable).
Status
Early but working. The runtime (window + system webview + invoke/emit bridge +
loopback asset server) is green headlessly, and precompiled x86_64-linux
packaging works — rake verify:linux builds the platform gem and proves it
installs and runs on a clean machine (system WebKitGTK only, no toolchain). Next:
macOS / Windows / aarch64 cross-builds + RubyGems publish, then richer window
options (menus, frameless).
License
MIT