The 100% Pure Ruby Frontend Web Framework in WebAssembly.
Build interactive Single-Page Applications (SPAs) entirely in Ruby running inside the browser via ruby.wasm — Zero JavaScript, Zero React, Zero Node, and Zero NPM dependencies.
- ⚡ 100% Pure Ruby Frontend: Write interactive web components, event listeners, and state management in native Ruby.
- 🔄 Reactive State Management: Define
state :count, default: 0. Updating state (self.count += 1) automatically re-renders component views. - 🌳 Virtual DOM Diffing: In-memory
VNodetree generation and diffing engine for optimal browser DOM rendering. - 🗺️ Client-Side SPA Routing: Single-page application route matching (
Router) for multi-view Ruby web apps. - 🛠️ Dev Server & CLI Tooling:
web_ruby_ui devlaunches a local WebAssembly dev server with instant browser hot-loading.
┌─────────────────────────────────────────────────────────────┐
BROWSER (WebAssembly Environment)
┌─────────────────────────────────────────────────────────┐
JS::Object (Browser DOM APIs)
▲
│ DOM Events (onclick, oninput) & Render Patches
▼
WebRubyUI::DOM (Event Bridge & JS Interop)
▲
│ In-Memory VNode Tree & Patch Diffing
▼
WebRubyUI::Component (Reactive State & HTML DSL)
└─────────────────────────────────────────────────────────┘
└─────────────────────────────────────────────────────────────┘
Add this line to your application's Gemfile:
gem 'web_ruby_ui'And then execute:
bundle installCreate a reactive Single-Page Application without touching JavaScript:
require 'web_ruby_ui'
class TodoApp < WebRubyUI::Component
state :items, default: [
{ id: 1, title: 'Learn Ruby WebAssembly', completed: true },
{ id: 2, title: 'Build WebRubyUI frontend framework', completed: true }
]
state :new_title, default: ''
def render
div(class: 'max-w-md mx-auto my-10 p-6 bg-white rounded-xl shadow-lg') do
h1(class: 'text-2xl font-bold text-indigo-600 mb-4') { 'RubyWasm Todo App 💎' }
# Add Todo Form
div(class: 'flex mb-4 gap-2') do
input(
type: 'text',
class: 'flex-1 px-4 py-2 border rounded-lg',
placeholder: 'What needs to be done?',
value: new_title,
oninput: ->(e) { self.new_title = e[:target][:value] }
)
button(
class: 'px-4 py-2 bg-indigo-600 text-white rounded-lg font-semibold',
onclick: -> { add_todo }
) { 'Add' }
end
# Todo List
ul(class: 'divide-y divide-gray-200') do
items.each do |item|
li(class: 'py-3 flex items-center justify-between') do
span(class: item[:completed] ? 'line-through text-gray-400' : 'text-gray-800') do
item[:title]
end
end
end
end
end
end
private
def add_todo
return if new_title.nil? || new_title.strip.empty?
self.items = items + [{ id: Time.now.to_i, title: new_title.strip, completed: false }]
self.new_title = ''
end
end| Command | Description |
|---|---|
web_ruby_ui new my_app |
Generates a new WebRubyUI project structure |
web_ruby_ui dev |
Launches a local WebAssembly web server at http://localhost:8000 |
web_ruby_ui build |
Packages standalone index.html for production deployment |
MIT License.