Crate respo

source ·
Expand description

Tiny virtual DOM library, compiles to WebAssembly, runs in browser, building interactive web apps with declarative code.

This library is experimental, heavily influenced by React.js and ClojureScript. Previously implementeded in ClojureScript and Calcit.

Respo Logo

To build UI:

  • there’s Virtual DOM, although simplified, still flexible for declarative UI
  • CSS with Rust macros, I call it “CSS in Rust”
  • Effects, flow from data to DOM, for patching DOM manually on data change
  • respo::ui provides basic style. Also try Modal, dialog, drawer components.

To manage states:

  • Rust enum and pattern matching it really nice for Elm-style action dispatching
  • global states tree and cursor to maintain states, may not be familiar but still being handy
  • you may also write shared component like a “plugin” to manage states.

To optimize:

  • components and elements are in functions, available for memoize
  • well, it’s Rust, you can do more…

Meanwhile it does not support React features such as:

  • ❌ updating data from render. Respo enforces “unidirectional data flow”. That’s not allowed
  • ❌ hooks API and context. Respo uses plain functions without tricky internal states
  • …does not have many other advanced features from React

Rust and WebAssembly lacks tricks for hot reloading, it’s suggested to use trunk to edit and reload the project during development. App states including components states can be saved to local storage and reloaded.

To start project, create your structs to implement traits:

  • RespoStore for global states and states tree, and RespoAction for updating
  • RespoApp for MVC overview of the app, and more views, bind events

say app is called app, you start app with app.render_loop(). Check Workflow for a working example.


  • Define CSS styles in Rust and generate CSS class-name.
  • Respo does not provide local states in components, but a global states tree. RespoStatesTree tree has concept of “cursor”, which is a path to the current state in the tree. use branch.pick(name) to get a child branch, and branch.set_in_mut(change) to update the tree.
  • Some pre-defined styles for layout fonts, and form elements. Highly coupled with styles from .


  • a macro for creating a function with a named node
  • wraps on top of web_sys::console.log_1.
  • macro to create a public function of CSS rules with a slice at current file scope,
  • macro to create a public function of CSS rules(up to 5 tuples) at current file scope,
  • wraps on top of web_sys::console.warn_1.


  • dispatch function passed from root of renderer, call it like
  • internal abstraction for a component
  • internal abstraction for an element
  • a key for referencing a child node, use a value that can be converted to string


  • Internal enum for effect types. you only need this if you override RespoEffect .run().
  • event wraps on top of DOM events
  • an Element or a Component


  • guide for actions to be dispatched expecially for how you update states
  • A template for a Respo app
  • trait for component effects you can declare mounted, beforeUpdate, updated, beforeUnmount methods to handle lifecycle events, mainly for manually manipulating DOM
  • it has a states tree inside, and it does update itself