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.
In this combination, each can play to his strengths.
You will love it!
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.
To models, where you want to use the to_svelte helper, add exposes_to_svelte, for example:
class Book < ApplicationRecord
exposes_to_svelte
end
3. Install and run the Showcase
rails g svelte_on_rails:showcase
- Restart your app
- open Browser on localhost:3000/svelte_on_rails_showcase
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.loginCount.label }: { user.loginCount }</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.
- 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- New in v10 (experimental) 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