Skip to content

Mobile PWA: secure-context service worker (offline shell) + Tailscale HTTPS for full Android install #192

Open

Description

@johannesjo

Summary

Add a secure-context-gated service worker (offline app shell) and a Tailscale HTTPS path so the mobile app becomes a fully installable PWA on Android/Chrome — not just iOS add-to-home-screen.

This is follow-up step 5 of 5 from the "autoconnect to mobile + installable PWA" work. Steps 1–3 have landed (auto-start server, manifest + icons, reconnect screen).

Background: why a manifest alone isn't enough

The remote server serves plain HTTP on a LAN IP (http://192.168.1.x:7777). That is not a secure context, and:

  • Service workers won't register over HTTP on a non-localhost origin → no offline shell, and Chrome won't show the "Install app" prompt / generate a WebAPK.
  • getUserMedia is also blocked → in-PWA QR-camera scanning can't work over HTTP either.
  • iOS Safari is the exception: "Add to Home Screen" works for any page (already shipped via the manifest in step 2), without a service worker.

So full installability requires a real HTTPS origin. The clean way to get one for a localhost service is Tailscale (tailscale serve → https://<machine>.<tailnet>.ts.net, trusted cert), which also gives a stable IP across networks/restarts — ideal for an origin-locked PWA.

Proposed solution

  1. Minimal service worker in src/remote/ (emitted into dist-remote/):
    • Pre-cache / cache-first the app shell (HTML, JS, CSS, icons, manifest).
    • Never cache /api/* or /ws (network-only) — these are dynamic and token-scoped.
    • Register it only when isSecureContext so it's a no-op over plain HTTP (no console errors on WiFi).
  2. Server caching headers: the static handler currently serves all non-HTML as immutable (electron/remote/server.ts). The service-worker file must be served no-cache (or short max-age) so SW updates propagate; revisit the manifest's caching too.
  3. Tailscale HTTPS guidance / integration: document tailscale serve (or detect/offer to run it) so users get a secure origin. The app already detects Tailscale IPs and offers a WiFi/Tailscale toggle in ConnectPhoneModal.

Acceptance criteria

  • Over a secure origin (Tailscale HTTPS / localhost), the service worker registers and the app shell loads offline.
  • Over plain HTTP (WiFi), SW registration is skipped cleanly — no errors, app still works as today.
  • /api/* and /ws are never served from cache.
  • The SW file is served with no-cache; updates roll out without a year-long immutable cache.
  • Chrome (Android) shows the install prompt when served over Tailscale HTTPS.
  • README/docs describe the Tailscale HTTPS setup for full install.

Touch points

  • src/remote/ — service worker source + registration (guarded by isSecureContext).
  • src/remote/index.html / index.tsx — SW registration entry.
  • electron/remote/server.ts — cache-control for the SW file; ensure SW scope path is served correctly.
  • README.md / PRIVACY.md — Tailscale HTTPS instructions.

Note

iOS already gets a standalone home-screen app over HTTP (shipped in step 2). This issue is specifically about Android/Chrome full install + offline shell, which is a web-platform requirement (secure context), not something we can shortcut in code.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions