via spring preloader in process 12345 invoke rails insert event: Tropical-On-Rails insert schedule: 2026-04-10 insert location: São-Paulo status confirmed create generators_are_apis.live create talks/tor26/slides.html.erb Talk successfully generated. Ready to run at Tropical On Rails.
❏ Act II — What bad DX looks like. ❏ Act III — What good DX looks like. ❏ Act IV — The bigger picture. We’re gonna go through 4 acts. Tropical On Rails 2026
❏ Act II — What bad DX looks like. ❏ Act III — What good DX looks like. ❏ Act IV — The bigger picture. We’re gonna go through 4 acts. Tropical On Rails 2026
❏ Act II — What bad DX looks like. ❏ Act III — What good DX looks like. ❏ Act IV — The bigger picture. Acts we’re following on this talk. Tropical On Rails 2026
btn create app/components/jet_ui/btn_component.rb create app/assets/stylesheets/jet_ui/btn.css create test/components/jet_ui/btn_component_test.rb create test/components/previews/jet_ui/btn_component_preview.rb # No --no-test. No --no-preview. No flags at all. # The generator decided for you. Tropical On Rails 2026
❏ Act II — What bad DX looks like. ❏ Act III — What good DX looks like. ❏ Act IV — The bigger picture. Acts we’re following on this talk. Tropical On Rails 2026
jet_ui:eject btn rails g jet_ui:eject btn card # Documented convention: # use the component short name. The name should tell you exactly what you'll get. Before. After. Principle 1. Naming is a contract. Tropical On Rails 2026
JetUi components into your app for local customisation." argument :components, type: :array, banner: “component [component …]”, desc: “Component(s) to eject (e.g. btn card)” def eject_components components.map(&:downcase).each do |name| MANIFEST[name][:files].each do |entry| template entry[:src], entry[:dest] end end end end Tropical On Rails 2026
JetUi::EjectGenerator < Rails::Generators::Base # rest of the generator logic here def eject_components components.each do |component| say "Ejecting #{component}..." # logic for generating files say " #{component} ejected.", :green end end def print_next_steps say "Done! Ejected: #{components.join(', ')}", :green say "Run your tests: bundle exec rake test", :cyan end end
creates files for # a component that does not exist. $ rails g jet_ui:eject buton error Unknown component: buton Available: btn, card, modal, alert, badge Did you mean? btn Example: rails g jet_ui:eject btn card Before. After. Principle 4. Errors should tell how to fix them.
JetUi::EjectGenerator desc "Like jet_ui:eject, but also generates Storybook stories." def generate_stories components.each do |component| template "story.js.tt", "stories/jet_ui/#{component}_component.stories.js" end end end Tropical On Rails 2026
❏ Act II — What bad DX looks like. ❏ Act III — What good DX looks like. ❏ Act IV — The bigger picture. Acts we’re following on this talk. Tropical On Rails 2026
via spring preloader in process 12345 invoke rails insert event: Tropical-On-Rails insert schedule: 2026-04-10 insert location: São-Paulo status confirmed create generators_are_apis.live create talks/tor26/slides.html.erb Talk successfully generated. Ready to run at Tropical On Rails.