#ui #html #native #javascript #cross-platform-ui

yanked joestar-html

Wry-based simple HTML5-based native UI platform for Rust - HTML Goodies

4 releases

0.1.3 Mar 25, 2023
0.1.2 Mar 16, 2023
0.1.1 Mar 14, 2023
0.1.0 Mar 13, 2023

#45 in #cross-platform-ui

35 downloads per month


953 lines

Project Joestar


Joestar is a Wry based simple WebUI platform that provides a simple API for creation, management and observation of DOM elements. Suitable for basic cross-platform UIs that require no platform-related unsolvable bugs or unimplemented features (like IME support...).


Another Toolkit

There are AN AWFUL LOT of UI toolkits out there. You can even use GTK and Qt here with Rust, why bother creating another one?

This is not another...

  • ...qml-rs or gtk-rs: It's really small (not counting Wry) with only one source file.
  • ...imgui or egui: It's not immediate-mode UI.
  • ...relm4 or dioxus: It does not implement a particular MVC system or follow a specific design pattern.

Not Tauri

It seems to be easier to just use tauri and write the UI things in ECMAScript. Why bother wrapping it into Rust and use it through an exotic interface?

If your App need a sophisticated UI that involve heavy theming and layout management, then you would want Next.js and Vite with Tauri instead. Visit their websites to learn more about how you can take advantage of them.

Joestar is dead simple, to an extent that it's ONLY suitable for small apps that would just want to be clickable. It can theoretically do most things HTML5 and ECMA can, but it's not designed for that.

Called Joestar

It's named after Joseph Joestar, a famous JoJo's Bizarre Adventure character.


Required packages are joestar and joestar-html.

use joestar::{Callback, joestar_terminate, launch_runtime, Model, Spec, View};
use joestar_html::{AgentExt, button, div, h1, input, p};

fn main() {

fn user_main() {
    let main = View::new(Spec {
        title: "Main".to_string(),
        size: (800, 600),
    let main_ord = main.ord();

    main.on_close_request(move || {
        println!("See you next time!");

            h1("Hello World!"),
            p("This is a paragraph."),
            button("Click me!")

    main.lookup("button1").on_click(|detail| {
        println!("Click: {:#?}", detail);

    main.lookup("input1").on_input(|detail| {
        println!("Input: {:#?}", detail);


~567K SLoC