- 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>
62 lines
3.7 KiB
Markdown
62 lines
3.7 KiB
Markdown
# 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](./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](./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](../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](./mobile-app-plan.md) (section 12 for the bootstrap
|
|
checklist, section 9 for the AGPL / App Store licensing path).
|