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

The future of Rails begins in the browser

The future of Rails begins in the browser

With a mature community and adoption by prominent tech veterans, Ruby on Rails already has a strong foundation, and these elements define both the present state of the framework, as well as its short-term future. But the long-term future of the framework is an equation that will depend heavily on the opposite end of the equation: namely, the newcomers, those who will take their first steps on Rails.

But will those first steps look like? Imagine being able to learn and play with Rails without the need to deal with installations or development environments. What if the next generation of Rails developers could start using something easily accessible to everyone: the browser!
Sounds like science fiction? Hardly! The fact is, interactive web-based tutorials, learning materials, and playgrounds play a critical role in wider technology adoption. We’re certain this is the future–and Rails must be a part of that future.

Join us on our journey to bring the “Getting Started with Rails” experience right into your browser. We’ll do this with the help of some new technologies: WebAssembly, WebContainers and in-browser databases!

Avatar for Albert Pazderin

Albert Pazderin

July 14, 2025
Tweet

Other Decks in Technology

Transcript

  1. IDE, Node.js runtimS Terminal, file syste1 npm instal All in

    the browserÈ no server attacheF Zero-setu development experience
  2. Can we bring the same zero-setup UÄ to the Rails

    world? Where it could be the most beneficial (spoiler: yes, we can0 (spoiler: learning)
  3. C Ruby Web browsers Standalone runtimes x86 ARM WASM .wasm

    Compiler (e.g. LLVM) Rust C Ruby Web browsers Standalone runtimes x86 ARM WASM .wasm Compiler (e.g. LLVM) Rust
  4. Bringing Ruby to the Browser: ruby.wasm ruby.wasm WASM WASI Packaging

    toolchain g Pre-compiled Ruby Runtimes g Gem packaging toolchain
  5. Bringing Ruby to the Browser: ruby.wasm G Pre-compiled Ruby Runtimes

    G Gem packaging toolchain G Compatibility patches ruby.wasm WASM WASI Packaging toolchain + patches
  6. Web Applicaiton (main JS thread) WebContainer runtimH (isolated Web Worker)

    WebContainer API Client Terminal UI Node.js Runtim™ (V8 based) Virtual File Systek (in memory) Service WorkeŒ (browser-level network proxy) (HTTP Traffic) (HTTP Traffic) Preview Iframe
  7. Web Applicaiton (main JS thread) WebContainer runtimH (isolated Web Worker)

    WebContainer API Client Terminal UI Node.js Runtim™ (V8 based) Virtual File Systek (in memory) Service WorkeŒ (browser-level network proxy) (HTTP Traffic) (HTTP Traffic) Preview Iframe
  8. Web Applicaiton (main JS thread) WebContainer runtimH (isolated Web Worker)

    WebContainer API Client Terminal UI Node.js Runtim™ (V8 based) Virtual File Systek (in memory) Service WorkeŒ (browser-level network proxy) (HTTP Traffic) (HTTP Traffic) Preview Iframe
  9. Web Applicaiton (main JS thread) WebContainer runtimH (isolated Web Worker)

    WebContainer API Client Terminal UI Node.js Runtim™ (V8 based) Virtual File Systek (in memory) Service WorkeŒ (browser-level network proxy) (HTTP Traffic) (HTTP Traffic) Preview Iframe
  10. Web Applicaiton (main JS thread) WebContainer runtimH (isolated Web Worker)

    WebContainer API Client Terminal UI Node.js Runtim™ (V8 based) Virtual File Systek (in memory) Service WorkeŒ (browser-level network proxy) (HTTP Traffic) (HTTP Traffic) Preview Iframe
  11. Web Applicaiton (main JS thread) WebContainer runtimH (isolated Web Worker)

    WebContainer API Client Terminal UI Node.js Runtim™ (V8 based) Virtual File Systek (in memory) Service WorkeŒ (browser-level network proxy) (HTTP Traffic) (HTTP Traffic) Preview Iframe
  12.  É È Ç Æ Å Ä Ã À 1Á

    1 1É 1È 1Ç 1Æ 1Å 1Ä 18 module module class def self require new en" en! en" end RackuU Handlee WASIServee . (app, options1 port options[ 2 ::Rack:: ::IncomingHandler. (app1 a ::Wasmify::ExternalCommands.server(port1 register , WASIServee run ** = = "rack/wasi/incoming_handler‡ :Port WASI :wasi # Init a global handler for the ap€ $incoming_handler # Signal to the JS host that the server is reads
  13. Rack::WASI::IncomingHandler ) ' & % $ # " ! 

    10 class def en2 end Rack:: ::IncomingHandlei (req, resE request Rack::MockRequest.env_for(uri.to_s, headersD response .call(requestD WASI handle # parse headero # ..f # ..f @app # handle responsp = =
  14. express.js 1. Receives HTTP request 2. Registers the request to

    the global scope 7 . Unpacks the data from the ruby response 8. Build & send the final response to the client 3. Invokes vm.evalAsync() & await rails.wasm 4. Reads request data from "JS.global" 6. Packages response into JS proxy object 5. Converts request into a standard Rack env hash & @app.call(env) Promise resolve trigger wm.evalAsync()
  15. express.js 1. Receives HTTP request 2. Registers the request to

    the global scope 7 . Unpacks the data from the ruby response 8. Build & send the final response to the client 3. Invokes vm.evalAsync() & await rails.wasm 4. Reads request data from "JS.global" 6. Packages response into JS proxy object 5. Converts request into a standard Rack env hash & @app.call(env) Promise resolve trigger wm.evalAsync()
  16. express.js 1. Receives HTTP request 2. Registers the request to

    the global scope 7 . Unpacks the data from the ruby response 8. Build & send the final response to the client 3. Invokes vm.evalAsync() & await rails.wasm 4. Reads request data from "JS.global" 6. Packages response into JS proxy object 5. Converts request into a standard Rack env hash & @app.call(env) Promise resolve trigger wm.evalAsync()
  17. express.js 1. Receives HTTP request 2. Registers the request to

    the global scope 7 . Unpacks the data from the ruby response 8. Build & send the final response to the client 3. Invokes vm.evalAsync() & await rails.wasm 4. Reads request data from "JS.global" 6. Packages response into JS proxy object 5. Converts request into a standard Rack env hash & @app.call(env) Promise resolve trigger wm.evalAsync()
  18. express.js 1. Receives HTTP request 2. Registers the request to

    the global scope 7 . Unpacks the data from the ruby response 8. Build & send the final response to the client 3. Invokes vm.evalAsync() & await rails.wasm 4. Reads request data from "JS.global" 6. Packages response into JS proxy object 5. Converts request into a standard Rack env hash & @app.call(env) Promise resolve trigger wm.evalAsync()
  19. express.js 1. Receives HTTP request 2. Registers the request to

    the global scope 7 . Unpacks the data from the ruby response 8. Build & send the final response to the client 3. Invokes vm.evalAsync() & await rails.wasm 4. Reads request data from "JS.global" 6. Packages response into JS proxy object 5. Converts request into a standard Rack env hash & @app.call(env) Promise resolve trigger wm.evalAsync()
  20. express.js 1. Receives HTTP request 2. Registers the request to

    the global scope 7 . Unpacks the data from the ruby response 8. Build & send the final response to the client 3. Invokes vm.evalAsync() & await rails.wasm 4. Reads request data from "JS.global" 6. Packages response into JS proxy object 5. Converts request into a standard Rack env hash & @app.call(env) Promise resolve trigger wm.evalAsync()
  21. express.js 1. Receives HTTP request 2. Registers the request to

    the global scope 7 . Unpacks the data from the ruby response 8. Build & send the final response to the client 3. Invokes vm.evalAsync() & await rails.wasm 4. Reads request data from "JS.global" 6. Packages response into JS proxy object 5. Converts request into a standard Rack env hash & @app.call(env) Promise resolve trigger wm.evalAsync()
  22. express.js 1. Receives HTTP request 2. Registers the request to

    the global scope 7 . Unpacks the data from the ruby response 8. Build & send the final response to the client 3. Invokes vm.evalAsync() & await rails.wasm 4. Reads request data from "JS.global" 6. Packages response into JS proxy object 5. Converts request into a standard Rack env hash & @app.call(env) Promise resolve trigger wm.evalAsync()
  23.   È Ç Æ Ä Ã Â À 1Á

    1 1 1È 1Ç 1Æ 1Ä 1à 1 1À 2Á 2 2 2È 2Ç 25 import from export default class async const await this this async await this null repl E IRBRepl Y () Y prompt .vm. ( Q repG . ({ prompt, eval .eval, writer rubyWriter }Q . ( , () process. ())D 5 V (cmd, _, _, callback) Y result .vm. ( ${cmd} )D ( , result)D 5 } "node:repl" h require "irbn class IRB::Ir‡ def eval_code(codew # ..s enq enp $irb = IRB::Irb.new(nil, IRB::StdioInputMethod.neww ` 'exit' `$irb.eval_code( )` start evalAsync start on exit eval evalAsync callback = : : => =
  24.  É Ç Æ Å Ä Ã Â À 1Á

    1 1É 1Ç 1Æ 1Å 1Ä 1Ã 1Â 1À 2Á 2 22 export default class this async function const await this async function return new return this ExternalCommands X (port) X . (vm) X server (vm, {skipRackup })I server. (port, () X . ( ${port} )H . ( )H })H 2 1 () X . (vm) X IRBRepl(vm). ()H 2 1 (vm) X . (vm)H 2 } server command createRackServer listen log log console command start invoke command = = : => console console = true `Express.js server started on port ` `Use Ctrl-C to stop`
  25.  É È Ç Å Ä Ã Â À 1Á

    1 1É 1È 14 import from const await const await const await await await { WebContainer } 4 webcontainerInstance WebContainer. ()5 files { {file {contents }}}5 webcontainerInstance. (files)5 process webcontainerInstance. ( , [ ])5 process.exit5 webcontainerInstance. ( , [ , ])5 webcontainerInstance. ( , (port, url) (iframeEl.src url)); '@webcontainer/api' "..." 'npm' 'install' 'npm' 'run' 'dev' 'server-ready' // Instantiatinf // File syste” // `npm install‘ // `npm run dev‘ // Previe = = : : : = => = boot mount spawn spawn on 'package.json'
  26. TutorialKit UI WebContainer runtime rails.wasm Ruby VM: WASM + WASI

    Gems Native extensions System tools PGLite Rack-compatibl— web server Lesson files Previep Iframe T erminal UI App code
  27. TutorialKit UI WebContainer runtime rails.wasm Ruby VM: WASM + WASI

    Gems Native extensions System tools PGLite Rack-compatibl— web server Lesson files Previep Iframe T erminal UI App code
  28. TutorialKit UI WebContainer runtime rails.wasm Ruby VM: WASM + WASI

    Gems Native extensions System tools PGLite Rack-compatibl— web server Lesson files Previep Iframe T erminal UI App code
  29. TutorialKit UI WebContainer runtime rails.wasm Ruby VM: WASM + WASI

    Gems Native extensions System tools PGLite Rack-compatibl— web server Lesson files Previep Iframe T erminal UI App code
  30. TutorialKit UI WebContainer runtime rails.wasm Ruby VM: WASM + WASI

    Gems Native extensions System tools PGLite Rack-compatibl— web server Lesson files Previep Iframe T erminal UI App code
  31. TutorialKit UI WebContainer runtime rails.wasm Ruby VM: WASM + WASI

    Gems Native extensions System tools PGLite Rack-compatibl— web server Lesson files Previep Iframe T erminal UI App code