Upgrade to Pro — share decks privately, control downloads, hide ads and more …

TutorialKit.rb: interactive Ruby gem docs power...

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

TutorialKit.rb: interactive Ruby gem docs powered by Wasm

Talk from RubyKaigi 2026, Hakodate, April 22, 2026.

What if trying a Ruby gem was as easy as opening a web page — no local setup, no bundle install, no version headaches? TutorialKit.rb enables interactive, runnable tutorials for Ruby gems directly in the browser by combining Ruby on WebAssembly with an in-browser development runtime. This talk covers the Ruby Association Grant-funded work behind it: the browser → WebContainer → ruby.wasm architecture, the Ruby-to-WebContainer HTTP bridge, and the build and distribution pipeline.

Avatar for Albert Pazderin

Albert Pazderin

April 22, 2026

More Decks by Albert Pazderin

Other Decks in Programming

Transcript

  1. TODO: the talk Framework overview Tutorial capabilities Framework capabilities Framework

    architecture Ruby Association Grant work What comes next
  2. TODO: the talk Framework overview Tutorial capabilities Framework capabilities Framework

    architecture Ruby Association Grant work What comes next : "Let's jump in!"
  3. TODO: the talk Framework overview Tutorial capabilities Framework capabilities Framework

    architecture Ruby Association Grant work What comes next : "Let's build!"
  4. my-tutorial/ ├── src/ │ ├── content/tutorial/ │ │ ├── 1-getting-started/

    │ │ └── meta.md │ └── templates/default/ │ ├── app/ │ ├── config/ │ └── Gemfile ├── ruby-wasm/ │ ├── Gemfile │ └── boot.rb # lesson content (MDX) # the Rails app (runs in the browser) # the Rails app for ruby.wasm module
  5. ├── package.json └── astro.config.mjs 1-welcome/ ├── content.mdx # lesson text

    ├── _files/ # starting state │ ├── app/controllers/pages_controller.rb │ ├── app/views/pages/home.html.erb │ └── config/routes.rb └── _solution/ ├── app/controllers/pages_controller.rb # finished state ├── app/views/pages/home.html.erb └── config/routes.rb
  6. content.mdx --type: lesson title: Welcome focus: /app/controllers/pages.rb previews: - [3000,

    "Rails app"] filesystem: watch: true --- # sidebar label # file opened in editor # live-preview port # reflect edits live # Welcome This lesson covers the basics: - how Rails routes a request - how a controller responds - how ERB renders a view Edit the controller to return a greeting, then reload the preview.
  7. my-tutorial/ ├── AGENTS.md └── .agents/ └── skills/ ├── tutorial-quickstart/ ├──

    tutorial-content-structure/ ├── tutorial-lesson-config/ ├── rails-lesson-recipes/ ├── rails-file-management/ └── rails-wasm-author-constraints/
  8. TODO: the talk Framework overview Tutorial capabilities Framework capabilities Framework

    architecture Ruby Association Grant work What comes next : "Let me show you how it works!"
  9. TODO: Rails in a browser Ruby interpreter Static filesystem Dynamic

    filesystem Processes & shell Web server Database UI
  10. TODO: Rails in a browser Ruby interpreter Static filesystem Dynamic

    filesystem Processes & shell Web server Database UI
  11. TODO: Rails in a browser Ruby interpreter Static filesystem Dynamic

    filesystem Processes & shell Web server Database UI
  12. 2-layer filesystem /usr/ 🔨 BUILD TIME ▶️ RUNTIME ruby.wasm host

    FS stdlib /workspace/ /rails-vm/ user app gems · boot · Gemfile wasi-vfs · read-only WASI preopen · read-write
  13. https://my-ruby-tutorial.com Web Application (main JS thread) WebContainer API Client ↓

    (shell I/O) Terminal UI (files) Editor (HTTP) Preview Iframe WebContainer runtime (isolated Web Worker) Node.js Runtime (V8-based) ↓ (HTTP Traffic) ↔ Virtual File System (in memory) Service Worker (browser-level network proxy)
  14. TODO: Rails in a browser Ruby interpreter Static filesystem Dynamic

    filesystem Processes & shell Web server Database UI
  15. Preview iframe Express (WebContainer) JS globals Ruby (Rack) GET /articles

    req-42 = {method, path, headers, body} res-42 = {} evalAsync(handle("42")) read req-42 build Rack env · dispatch res-42 ← {status, headers, body} promise resolves HTTP response Preview iframe Express (WebContainer) JS globals Ruby (Rack)
  16. TODO: Rails in a browser Ruby interpreter Static filesystem Dynamic

    filesystem Processes & shell Web server Database UI
  17. TutorialKit UI WebContainer runtime Rackcompatible web server PGLite Lesson files

    Terminal UI ruby.wasm Gems Native extensions System tools Ruby VM: WASM + WASI App code Preview Iframe
  18. TODO: the talk Framework overview Tutorial capabilities Framework capabilities Framework

    architecture Ruby Association Grant work What comes next
  19. class Gem::Request def perform_request(req) response = JS.eval(<<~JS).await return fetch(#{uri.to_s.to_json}, {

    ... }) .then(response => { ... }) JS Net::HTTPResponse.new("1.1", response[:status], "OK").tap do |r| r.body = response[:body] response[:headers].each { |k, v| r[k] = v } end end end
  20. Net::HTTP.prepend(Module.new do def request(req, body = nil, &block) uri =

    reconstruct_url(req) response = WasmHTTP::Connection.new.request( uri, method: req.method, headers: headers(req), body: req.body ) yield response if block # Faraday's :net_http adapter reads status here response end def connect; end def do_start; @started = true; self; end def do_finish; @started = false; end end)
  21. WASI preopen (fd → /gems) Ruby VM (WASM) JS host

    require "rails" fd_stat(fd, "rails.rb") WASM ↔ JS boundary — imported JS fn stat(path) WebContainer FS lookup stat struct return value Ruby VM (WASM) WASI preopen (fd → /gems) JS host
  22. npm run pack:wasm npm run build:wasm # pure-Ruby gems only:

    seconds # C extensions changed: minutes
  23. gem install Gem author Ruby runtime cross-compile per platform pick

    matching .gem bcrypt_ext.so (x86_64-linux) require "bcrypt" dlopen("bcrypt_ext.so") native functions available gem install Ruby runtime
  24. TODO: the talk Framework overview Tutorial capabilities Framework capabilities Framework

    architecture Ruby Association Grant work What comes next
  25. WASI Preview 1 — today WASI Preview 2 — ahead

    Files, clocks, random, stdio ❌ Sockets ❌ Threads Everything in P1 ✅ Native sockets ✅ Better component model ✅ Standardized capabilities →
  26. Two gates before we can experiment 🔬 ruby.wasm WASI P2

    support Experimental branch already exists. Soft blocker. ⏳ WebContainer WASI P2 support StackBlitz would need to add support. External dependency.
  27. TODO: drop WebContainer Swap HTTP serving to a Service Worker

    (mastodon.wasm pattern) Build a virtual filesystem + editor sync Terminal + process layer ( rails , bundle , etc.)
  28. Kudos Yuta Saito Vladimir Dementyev Svyatoslav Kruykov Grant mentor Rails

    tutorial POC runruby.dev ruby.wasm Action Policy tutorial JS-bridge HTTP pattern "Rails on Wasm" book