Files
gitmost/docs/mobile-bootstrap.md
claude code agent 227 2f5b520af2 chore(offline-sync): tighten SW denylist, drop dead /api cache + http localhost CORS
- Service worker (vite-plugin-pwa/Workbox): add /share/, /mcp, and /robots.txt
  to navigateFallbackDenylist so the SPA app-shell never shadows those
  server-rendered routes (they mirror the server static-serve exclude list — the
  share SEO/OG HTML, the MCP endpoint, and robots.txt must come from the server).
- Remove the dead /api GET NetworkFirst Workbox rule (api-get-cache): offline
  reads are served by the persisted TanStack Query cache (IndexedDB) + y-indexeddb,
  never by an SW HTTP cache, so caching GET /api only risked stale responses. All
  /api is now NetworkOnly. clearOfflineCache still deletes any legacy api-get-cache
  defensively (comment updated to note it is no longer created).
- CORS: drop the cleartext 'http://localhost' native-WebView origin. The Capacitor
  shell uses the secure scheme (capacitor.config cleartext:false, default Android
  scheme https, iOS hosted via CAP_SERVER_URL), so no native client uses it;
  allowing it only widened the credentialed-CORS surface. Keeps capacitor://,
  ionic://, and https://localhost.
- docs/mobile-bootstrap.md: replace the inaccurate 'hand-rolled service worker'
  description with the real Workbox generateSW setup (prompt registration via
  virtual:pwa-register, production-only, denylist, NetworkOnly, RQ/y-indexeddb
  offline reads) and drop http://localhost from the CORS origins list.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 15:15:50 +03:00

3.7 KiB

Mobile app bootstrap

Purpose: this document records what has been bootstrapped in the repo to enable a mobile app for Gitmost, per the first-step checklist in docs/mobile-app-plan.md section 12.

What is in the repo now

  • PWA: web app manifest plus a service worker generated by vite-plugin-pwa using Workbox (strategies: "generateSW" — not hand-rolled). The SW is built for production only (devOptions: { enabled: false }) and uses registerType: "prompt", so the user is asked to apply an update rather than it auto-updating; registration goes through virtual:pwa-register/react (useRegisterSW) in apps/client/src/pwa/pwa-update-prompt.tsx, mounted from main.tsx and skipped inside the Capacitor native WebView. The SW precaches the app shell (globPatterns js/css/html/...) and serves navigateFallback: "index.html" for SPA routes, with navigateFallbackDenylist excluding the server-owned routes /api, /collab, /socket.io, /share/, /mcp, and /robots.txt. runtimeCaching keeps /collab, /socket.io, and all /api as NetworkOnly — offline reads are served by the persisted TanStack Query cache (IndexedDB) and y-indexeddb for the page Yjs doc, not by an SW HTTP cache. This lets the existing responsive web UI be installed and run as a Progressive Web App. See docs/offline-sync-plan.md for the full offline/sync design.
  • Backend mobile auth: opt-in token return from the login flow. The login request accepts a returnToken flag (must be sent as a JSON boolean) that makes the server include the auth token in the response body, and the server already accepts a Bearer token in the Authorization header. Note the global response interceptor wraps every payload, so the native client reads the token at response.data.authToken (not at the top level). A native client can store this token (Keychain / Keystore) and send it as Authorization: Bearer on each request.
  • Explicit CORS allowlist: the server reads a CORS_ALLOWED_ORIGINS env variable for the allowed origins, and always allows the native WebView origins (capacitor://localhost, ionic://localhost, https://localhost) so the mobile shell can call the API.
  • Optional OpenAPI / Swagger: an opt-in OpenAPI/Swagger surface gated behind the SWAGGER_ENABLED env flag, useful for developing the native client.
  • Capacitor config: capacitor.config.ts at the repo root. It targets the apps/client web build output (apps/client/dist) for the Android bundled mode, and on iOS loads the client from a hosted server via CAP_SERVER_URL (server.url) so the AGPL web client is not bundled into the .ipa (see mobile-app-plan section 9).

Remaining MANUAL / local steps (require Xcode / external accounts, out of scope here)

  • Run pnpm install to fetch the Capacitor packages and @nestjs/swagger.
  • Run pnpm run client:build to produce the web build in apps/client/dist.
  • Run npx cap add ios and/or npx cap add android to generate the native platform projects (these live outside version control; see .gitignore).
  • Set CAP_SERVER_URL for the iOS build so the shell loads the hosted client (AGPL-clean), then run pnpm run mobile:build / cap sync.
  • Set up push notifications: APNs for iOS and FCM for Android.
  • Obtain an Apple Developer account and the App Store / Play Console listings.
  • Confirm the AGPL iOS distribution decision (mobile-app-plan section 9) before shipping anything to the App Store.

See also

For the full background, rationale, and the licensing analysis, see docs/mobile-app-plan.md (section 12 for the bootstrap checklist, section 9 for the AGPL / App Store licensing path).