Ruby on Rails Hotwire Project Structure
Full Hotwire stack with Turbo and Stimulus. SPA-like experience with server-rendered HTML.
Project Directory
myapp/
Gemfile
Gemfile.lock
package.json
Rakefile
config.ru
app/
controllers/
application_controller.rb
posts_controller.rb
comments_controller.rb
Turbo stream responses
models/
application_record.rb
post.rb
broadcasts_to for Turbo Streams
comment.rb
views/
layouts/
application.html.erb
posts/
index.html.erb
show.html.erb
_post.html.erb
Turbo Frame partial
_form.html.erb
comments/
_comment.html.erb
create.turbo_stream.erb
Stream response
javascript/
Stimulus controllers
application.js
controllers/
application.js
index.js
Auto-load controllers
dropdown_controller.js
modal_controller.js
form_controller.js
channels/
Action Cable for Turbo Streams
application_cable/
helpers/
assets/
config/
application.rb
routes.rb
database.yml
cable.yml
WebSocket config
importmap.rb
JavaScript imports
environments/
initializers/
db/
test/
lib/
public/
bin/
Why This Structure?
Hotwire (HTML Over The Wire) delivers SPA-like experiences without JavaScript frameworks. Turbo handles navigation and form submissions, Turbo Streams update page fragments, and Stimulus adds behavior. Server renders HTML, client stays light.
Key Directories
- app/javascript/controllers/-Stimulus controllers for JavaScript behavior
- app/views/*/*.turbo_stream.erb-Turbo Stream templates for live updates
- app/channels/-Action Cable for WebSocket broadcasts
- config/importmap.rb-JavaScript dependencies without bundler
Turbo Streams Broadcast
# app/models/comment.rb
class Comment < ApplicationRecord
belongs_to :post
broadcasts_to :post
end
<%= turbo_stream_from @post %>
<%= render @post.comments %>
Getting Started
rails new myapp(Hotwire included by default)rails generate scaffold Post title:stringrails db:migrate- Add
broadcasts_toto models for live updates bin/dev(starts Rails + CSS watcher)
When To Use This
- Traditional apps wanting SPA-like feel
- Real-time features (chat, notifications, dashboards)
- Teams without JavaScript framework expertise
- When you want to keep stack simple
- Progressive enhancement of existing Rails apps
Trade-offs
- Learning curve-Turbo Frames/Streams concepts take time
- Complex interactions-Very dynamic UIs may need more Stimulus
- WebSocket requirement-Turbo Streams broadcasting needs Action Cable
Naming Conventions
- Stimulus controllers-snake_case: dropdown_controller.js
- Turbo Stream templates-action.turbo_stream.erb
- Turbo Frame IDs-dom_id helper: post_1, comment_5