Updated November 10, 2026. Tested with Ruby 3.1, Rails 7.2.4, hotwire-spark 0.1.13 and the Tailwind setup from part 2 (tailwindcss-rails 4.7, Tailwind CSS v4), using Docker Desktop on macOS.
In the first post we set up a dockerized Rails app, and in the second we added Tailwind and daisyUI. There’s one more thing that makes this kind of setup much nicer to work in: hot reloading, so that the browser updates automatically whenever you save a change.
Right now you have to switch to the browser and refresh the page every time you edit a view or add a Tailwind class. That’s a small thing, but you do it hundreds of times a day.
Add hotwire-spark
hotwire-spark is a gem from the Hotwire team that watches your files and tells the browser when something changes. Add it to the development group in your Gemfile:
gem "hotwire-spark", group: :development
Our gems are installed when the Docker image is built, so rebuild the image and start everything up again:
docker-compose build
docker-compose up
That’s the whole setup. There’s nothing to add to your layout. In development, the gem injects its own script and tags into your pages. If you view the source of a page, you’ll see some spark meta tags and a script in the <head>.
How it works
The injected script opens a websocket connection back to your app, at /hotwire-spark. Meanwhile, the Rails server watches your project’s files. When one changes, it sends a message down the websocket, and the browser reacts:
- When a view, helper, controller, model or locale file changes, the page’s HTML is reloaded and morphed into place, rather than doing a full page refresh.
- When a CSS file changes, the stylesheet is swapped out in place.
- When a Stimulus controller changes, it’s reloaded.
By default, if there’s an app/assets/builds folder, the gem watches it for CSS changes. That’s exactly where the Tailwind watcher from part 2 writes its output, so the two pieces fit together without any extra configuration.
Try it out
With docker-compose up running, open http://localhost:3000 in your browser. Then edit app/views/home/index.html.erb and change the text of the heading. Save the file, and the page should update on its own.
Now try the full chain. Add a Tailwind class you haven’t used yet, like bg-rose-300, to an element in the same file and save. A few things happen in quick succession:
- Spark sees the view change and reloads the page’s HTML.
- The Tailwind watcher notices the new class and recompiles
app/assets/builds/tailwind.css. - Spark sees the CSS change and swaps in the new stylesheet.
A moment later the new styling shows up in the browser, and you didn’t have to touch it.
When I tested this, I watched the websocket messages while editing a view. A reload_html message arrived first, followed by a reload_css for /tailwind.css.
A few notes
- Hot reloading only runs in development. The gem is in the
developmentgroup and is switched off in other environments. - This depends on your file changes being noticed inside the container. It worked in my testing on macOS with Docker Desktop and the volume mount from part 1. If edits aren’t being picked up on your setup, look at the
webcontainer’s logs first.
Wrapping up
We now have a Dockerized Rails app with a Postgres database, Tailwind and daisyUI for styling, and hot reloading, all started with a single docker-compose up.