Rosa Gutierrez 975968b50f Only enable offline caching for Hotwire Native apps
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>
2026-03-10 10:20:54 +01:00
2024-06-21 13:19:56 +01:00
2025-12-02 13:35:58 -08:00
2024-06-21 13:19:56 +01:00
2026-03-09 21:53:43 -07:00
2024-06-21 13:19:56 +01:00
2025-11-21 09:15:19 +00:00
2025-12-04 09:59:17 -08:00
2025-10-09 13:24:01 -07:00
2025-12-02 20:37:58 +01:00
2025-11-28 15:53:58 +01:00
2024-06-21 16:42:48 +01:00
2025-12-12 17:26:50 +00:00

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.

S
Description
No description provided
Readme 62 MiB
Languages
Ruby 67.8%
HTML 14.6%
CSS 10.8%
JavaScript 5.6%
Shell 0.9%
Other 0.3%