Svelte on Rails
Combining two beautiful worlds: Rails backend power and Svelte frontend joy.
For most interfaces, Hotwire is already a great choice. But when you need richer frontend interactivity, Svelte becomes the perfect lightweight layer on top of your Rails app.
Installation + optional Showcase
Copy, paste, and run the following commands in your terminal:
1. Create a new Rails app
If you start from scratch:
rails new svelte-on-rails-testapp app --skip-javascript && cd svelte-on-rails-testapp
2. Install svelte-on-rails
bundle add svelte-on-rails
rails g svelte_on_rails:install
The installer is designed to be carefully and safe:
- it checks prerequisites
- it uses an isolated sandbox for checking npm dependencies before applying changes to the app.
- it won’t overwrite existing files without asking
Just follow the prompts.
3. Install and run the Showcase
rails g svelte_on_rails:showcase
- Restart your app
- open Browser on localhost:3000/svelte_on_rails_showcase
Additional: On Models, where you want to use the to_svelte helper, add exposes_to_svelte, for example:
class Book < ApplicationRecord
exposes_to_svelte
end
Code Example
View helper:
<%= svelte('components/Stats', user: @user.to_svelte(:login_count, :name) %>
Component:
app/frontend/javascript/components/User.svelte:
<script>
let { user } = $props();
</script>
<h1>{ user._schema.self.name } { user.name } { user._schema.login_count.label }: { user.login_count }</h1>
Output:
<h1>Benutzer Josef Logins: 77</h1>
<!--
the #to_svelte helper
• returns useful meta-data for models and columns
• serializes data
-->
On the server logs, with the «Completed Line»:
17:35:52 web.1 | [SOR] ...
17:35:52 web.1 | [SOR] Stats.svelte returned from cache (1.4ms)
17:35:52 web.1 | Completed 200 OK in 43ms ( ... | ... | Svelte: 2 cached, 1 rendered, 3.3ms)
# or
12:36:45 web.1 | Completed 200 OK in 831ms ( ... | ... | SVELTE BUILD FAILED!)
# or
12:36:45 web.1 | Completed 200 OK in 831ms ( ... | ... | Svelte: build, 3 warnings, 3 cached, 786.7ms)
# or
12:35:22 web.1 | Completed 200 OK in 44ms ( ... | ... | Svelte: 3 cached, 2.1ms)
When you see something like «SVELTE BUILD FAILED» you will find a detailed error message with the links to the files.
Before You Build Your First App
- Check out the Hotwire Svelte Helpers Example App:
- This set of helpers makes it easy to create dropdowns, tooltips, and modals with Svelte and Stimulus.
- It includes form helpers for Svelte that interact with the Rails backend.
- Z-index issues are solved by configurable rendering into a root-level container.
- Add some global translations:
- See configuration
- Consider using Svelte components within
app/views, just like partials:- See configuration
- Testing:
- For testing we use this Playwright setup.
- Important: The gem adds the class
hydratedto every component after it has finished hydrating. Append it to your selectors so tests don’t interact with a component before its event listeners are attached, for example:page.wait_for_selector(".my-component.hydrated .any-button").click - This aligns to the
.stimulus-connectedclass of@csedl/hotwire-svelte-helpers. - Important: The
hydratedclass is added to the root element of the Svelte component. This is different from thesvelte:optionstagoption,
- Performance:
- Add the
redisgem to your Gemfile and setuse_caching: trueinconfig/svelte_on_rails.yml. - Use
watch_changes: truein development only. - Check uncached props.
- Add the
Why?
Svelte`s reactivity is the missing piece for Rails+Hotwired.
Why was Svelte invented? Watch the Rethinking Reactivity video (especially 5:00–7:10).
Features
- Server-Side Rendering
- SSR Server (Default / similar to
react_on_rails pro)- Fine-grained fragment caching
- ActiveRecord integration – pass models directly with
.to_svelte- optional support for placing
.sveltecomponents directly inapp/views- Plays nicely with Hotwire Turbo (option: SSR only for initial page load)
- Fully integrated with
rails assets:precompile- Built-in interface for server → client communication via ActionCable / Turbo Streams
- Fully configurable
- Detailled logging for performance optimization and error detection
Enjoy it! 😉
For Questions or Issues, please open an issue on GitLab.
Best Regards,
Chris