This change conditionally renders the TurboOffline caching rules based on whether the request comes from a Hotwire Native app. Web browsers get a minimal service worker that only handles push notifications and a simple document fetch fallback. Why separate behavior for native vs web? ----------------------------------------- We want offline caching for Hotwire Native apps (where users expect app-like offline behavior) but not for regular web browsers. Why use ERB conditional rendering? ---------------------------------- We explored several approaches to detect Hotwire Native requests in the service worker: 1. User-Agent detection in fetch handler: Would be ideal, but Android WebViews override the User-Agent header with the system default when requests are intercepted by service workers, stripping the custom "Hotwire Native" identifier. 2. Custom header (X-Hotwire-Native) from native apps: Would require intercepting ALL requests at the native level using both WebViewClient.shouldInterceptRequest() and ServiceWorkerClient. Complex to implement and still incomplete coverage for all request types (navigation, resources loaded by HTML). 3. In-memory flag with IndexedDB persistence: Service workers can be terminated when idle and restart with fresh state. Reading from IndexedDB is async, but the decision to call respondWith() in a fetch handler must be synchronous. 4. Separate service worker URLs: Same theoretical churn problem as ERB rendering, with more complexity. Why ERB conditional rendering works in practice ----------------------------------------------- The main concern with conditional ERB rendering was "churn" — the service worker constantly updating as different client types fetch it. However, this only happens when web and native share storage on the same device. In practice, this is rare because: - Android native apps use isolated WebView storage - iOS doesn't support service workers in WebViews (yet) - Web browsers have completely separate storage So each context gets its own stable service worker without churn. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fizzy
This is the source code of Fizzy, the Kanban tracking tool for issues and ideas by 37signals.
Running your own Fizzy instance
If you want to run your own Fizzy instance, but don't need to change its code, you can use our pre-built Docker image. You'll need access to a server on which you can run Docker, and you'll need to configure some options to customize your installation.
You can find the details of how to do a Docker-based deployment in our Docker deployment guide.
If you want more flexibility to customize your Fizzy installation by changing its code, and deploy those changes to your server, then we recommend you deploy Fizzy with Kamal. You can find a complete walkthrough of doing that in our Kamal deployment guide.
Development
You are welcome -- and encouraged -- to modify Fizzy to your liking. Please see our Development guide for how to get Fizzy set up for local development.
Contributing
We welcome contributions! Please read our style guide before submitting code.
License
Fizzy is released under the O'Saasy License.