5 min read
Why does my Rails app need to become a desktop app?
Probably it doesn't, however in the odd case that it does, maybe Turbo Desktop is for you.
I have an upcoming talk this October at Tiny Ruby, the talk is titled "Turbo Desktop: Bringing Rails to desktop apps" And you might be thinking "Wait a second, I have a Rails app. It runs on all browsers without issues. Why would you want to turn it into a desktop app?"
Well, fair enough, and in all honesty for most apps the answer is genuinely "you don't". If your users open your app twice a week, do their thing and close the tab, the browser is your friend and you can stop reading here, but please don't, I worked hard on this one.
Usually on my regular work day, the following apps are opened on my desktop at all times: my terminal app, Spotify, and my email app.
These are apps that I could have in a browser tab, and sometimes I do, but my tabs get cluttered really fast, however I started noticing some characteristics these apps have that make me want to use the desktop version of them:
- - I want to have easy access to a badge that gives me notifications when I need it
- - I want to have easy global keyboard shortcuts where I can switch between these apps quickly enough
- - I want to see the apps on my dock (I'm a mac user) when I start my work day
Then came the point where I wanted to develop my own desktop apps based on my Rails apps, but to be honest I was already inclined to find a solution in my favorite programming language: Ruby, so I went window shopping.
The first option I looked into was Swift for macOS, something else for Windows, something else again for Linux. Again I'm a Mac user, so Swift sounded fun, but being one developer and having to maintain 3 different codebases, it really did not sound like a good option for me, I want to still have some free time in my life.
The second option I looked into was Electron, which works, and several apps I already use are on Electron. But the deal you make is that every app ships its own entire copy of Chromium. Your "hello world" is 150MB+ before you write a single feature. It felt a bit too much for me, especially with my use case.
Then I tried to write it in Ruby, Andy Maleh's Glimmer has been handling Ruby's GUI needs since 2007, a whole family of declarative DSLs, Glimmer DSL for SWT on JRuby, Glimmer DSL for LibUI on plain MRI Ruby with zero prerequisites, and several more, with bidirectional data-binding and native widgets on every platform.
You write a window block, bind your models with <=>, and you have a real desktop app: no browser, no server, works on a plane. If you are building a desktop tool from scratch and want to stay in Ruby the whole way down, Glimmer is genuinely great, and honestly, I'm just happy this option exists at all.
But it solves a different problem than mine: Glimmer is for building a new desktop app, and I already have a Rails app.
I want to be fair to all three of these, because they all solve real problems for real teams. But none of them felt right for the kind of app I had in mind: a Rails app, built by one dev who wants a desktop app without putting in a lot of effort.
So I started looking into Hotwire, and the idea is that your server is your app. HTML goes over the wire, the client stays thin, and all the logic, the state, the actual product, lives in one place: your Rails codebase.
Hotwire Native took that idea to mobile and it somehow clicked with what I wanted, an iOS or Android app can be a thin native shell around your existing web app, with small native "bridge" components when needed, I just needed to translate Hotwire Native to the desktop.
This is where Tauri comes in, Tauri is a framework for building desktop apps that, instead of bundling a whole browser like Electron, uses the webview your operating system already has. The shell around it is written in Rust, the binaries are tiny, and the resource usage is what you'd expect from a native app.
So Turbo Desktop is a Tauri shell that you point at your Rails app, and it gives you a desktop app that speaks Hotwire, with the same building blocks used in turbo-ios and turbo-android: path configuration to decide how each URL is presented (modal, new window, and so on), and bridge components for the desktop-specific parts, native notifications, menu bar items, file pickers, global keyboard shortcuts, the dock badge, the things that made you want a desktop app in the first place. And because Tauri uses the OS webview, the whole app ships at around 5 to 10 MB.
This is what the code looks like to create a new app:
npx turbo-desktop new myapp
Then on the Rails side, one gem so your app knows when it's running inside the desktop shell:
# Gemfile gem "turbo_desktop-rails"
And your views can do things like turbo_desktop_only { } for desktop-specific UI, while everything else stays exactly the same on the Rails side.
So I'll be talking about all of this, with actual code, actual demos, and probably at least one live failure, at Tiny Ruby in Helsinki. If you are around, come say hi, tell me what you think and if you are a desktop enthusiast too.
References:
- - Turbo Desktop — https://turbo-desktop.dev / https://github.com/aguspe/turbo_desktop
- - Glimmer (Andy Maleh) — https://github.com/AndyObtiva/glimmer
- - Hotwire Native — https://native.hotwired.dev
- - Tauri — https://tauri.app
- - Electron — https://www.electronjs.org
- - 37signals on Hotwire and HTML over the wire — https://hotwired.dev