Files
gmtool/docs/native-ipad-wrapper.md
T
slaguru666andClaude Opus 4.8 e79f643409 feat: native iPad wrapper — Capacitor iOS scaffold
Wrap the PWA in a thin native iOS shell (Capacitor 8):
- capacitor.config.json (webDir dist, appId uk.timevans.thedirector,
  iOS safe-area contentInset + theme background).
- @capacitor/{core,cli,ios} as devDependencies (web app keeps zero
  runtime deps); ios:add / ios:sync / ios:open / ios npm scripts.
- main.js skips service-worker registration under Capacitor
  (window.Capacitor.isNativePlatform) — assets are already local.
- iOS <meta> hints in index.html; .gitignore for native build output.
- docs/native-ipad-wrapper.md: full Xcode + CocoaPods build guide,
  incl. the keep-awake plugin note for the wake toggle in WKWebView.

The iOS project generation/build (npx cap add ios → Xcode) needs a Mac
with full Xcode + CocoaPods, which this env lacks; it is documented for
the user to run. tests/tools/capacitor-config.test.js guards the config.
211 tests pass; build clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 23:55:20 +01:00

3.5 KiB
Raw Blame History

The Director — native iPad wrapper (Capacitor)

The app ships as an offline-first PWA; this wraps that same build in a thin native iOS shell (a WKWebView) so it can be installed from Xcode / TestFlight and get a real home-screen app, splash screen, and App Store path. No app logic changes — Capacitor serves the dist/ build locally on the device.

The Capacitor config, scripts, and integration are committed. Generating and building the actual iOS project must be done on a Mac with the toolchain below — it cannot be produced without Xcode + CocoaPods.

Prerequisites (on the Mac)

  • Full Xcode (not just Command Line Tools). Then point the toolchain at it: sudo xcode-select -s /Applications/Xcode.app/Contents/Developer and accept the licence (sudo xcodebuild -license accept).
  • CocoaPods: brew install cocoapods (or sudo gem install cocoapods).
  • Node ≥ 20 (Capacitor 8) — already required to build the web app.

Check: xcodebuild -version and pod --version should both print a version.

One-time: generate the iOS project

npm install          # pulls @capacitor/core, cli, ios (devDependencies)
npm run ios:add      # = vite build → npx cap add ios   (runs pod install)

This creates ios/ (an Xcode project under ios/App). Commit it — it is the native project source. Generated/derived paths inside it are git-ignored (see .gitignore).

App icons + splash (once): drop a 1024×1024 source at resources/icon.png and a splash at resources/splash.png, then npx @capacitor/assets generate --ios.

Every build after a web change

npm run ios:sync     # = vite build → npx cap sync ios   (copies fresh web assets + plugins)
npm run ios:open     # opens ios/App/App.xcworkspace in Xcode
# or in one step:
npm run ios

In Xcode: pick your Team (Signing & Capabilities), choose an iPad simulator or a connected iPad, and Run (⌘R). For a device/TestFlight build you need an Apple Developer account and a signing profile.

Config

capacitor.config.json:

  • appId — uk.timevans.thedirector. Change this before the first ios:add (changing the bundle id after generation means regenerating or editing Xcode).
  • webDir: dist — the vite output the shell serves.
  • ios.contentInset: always + viewport-fit=cover in index.html handle the safe areas (notch / home indicator) so the Director Rail sits correctly.
  • backgroundColor matches the app theme so there is no white flash on launch.

iOS-specific notes

  • Offline: fully native — the web assets are bundled in the app, so it works with no network regardless of the service worker. The browser PWA still uses sw.js; the wrapper skips SW registration (window.Capacitor.isNativePlatform() in main.js) to avoid a redundant SW under the capacitor:// scheme.
  • Keep-awake (💡): navigator.wakeLock is unreliable inside WKWebView. For a solid screen-on toggle in the native build, add @capacitor-community/keep-awake and call KeepAwake.keepAwake() / .allowSleep() from the shell's wake toggle when window.Capacitor is present. The current toggle degrades gracefully until then.
  • Online art "Generate": works the same — it calls the GM-configured endpoint over the network when connected.
  • Orientation: the manifest requests landscape; set the same in Xcode (Deployment Info → iPad → Landscape only) so it matches at the table.