forge-mobile
Forge: mobile apps — React Native/Expo/Flutter: mobile app, iOS, Android, Expo, EAS, Flutter, apk, ipa, secure storage, deep link, App Store, Play Store.
SKILL.md.claude/skills/forge-mobile/SKILL.md
GitHubForge playbook — Mobile app (React Native / Expo / Flutter)
The mobile-dev specialist leads the native work under build-boss. Native UX/touch/layout defers to ui-boss; any backend/API the app calls defers to forge-integration; if it handles money defer to forge-payments. The core honesty rule for mobile: a Metro/dev bundler running is not a shipped app — the release binary must actually build and launch on a real device or emulator, and you must say so with evidence.
Hard rules (non-negotiable)
- A native build that actually installs. The app compiles to the real artifact (Android
.apk/.aab, iOS.ipa, or an Expo dev/prod build) and installs + launches on a device or emulator/simulator — verified, not assumed. "It runs in Expo Go / Metro" is not proof a standalone build works. - No secrets in the client bundle. A mobile bundle is trivially extractable (decompile the APK, read the JS bundle). Real secrets (API signing keys, private tokens) stay server-side behind an API; only genuinely public keys ship. Nothing sensitive committed or baked into the binary.
- Secure token storage. Auth tokens / credentials live in the OS secure store —
expo-secure-store,react-native-keychain(iOS Keychain / Android Keystore), or Flutterflutter_secure_storage— neverAsyncStorage/SharedPreferences/ plain files. - Least-privilege permissions with rationale. Request only permissions the app actually uses; iOS requires a real usage-description string per permission (
NSCameraUsageDescription, etc.) or App Store rejection; Android manifest kept minimal. - Offline-where-promised actually works. If offline use is promised, cached reads, queued writes, and a clear "no connection" state exist — not network calls that silently fail.
- No test/demo/mock data, no debug menus, no
__DEV__-only shortcuts in the release build. Release signing configured (Android release keystore, iOS distribution), version/build numbers set, app icon + splash present.
Team (conditional by stack/level)
Lead: build-boss. Native work: mobile-dev (RN/Expo/Flutter). Support: ui-boss (touch targets, safe-area/notch, keyboard, orientation, dark mode), test-boss (device/emulator QA — Detox or Maestro for RN, flutter test + integration_test for Flutter), security-boss (secure storage + secrets audit), typescript-reviewer and/or react-reviewer for RN code (RN is React-based). Backend calls: forge-integration team.
Skills / commands / MCP
RN / Expo / Flutter docs via Context7 (exact API + version behaviour). For React Native use /react-build + /react-review; for Flutter use /flutter-build + /flutter-review + /flutter-test. systematic-debugging for native/build/native-dependency failures. Popup/settings screens that are essentially web content can borrow forge-website conventions (real content, a11y). Opt-in / environment-gated deps (be honest): a real iOS build needs macOS + Xcode — not available on this owner's Windows host; use Expo EAS Build (cloud, requires an Expo account) or an Android target instead, and label an iOS build not-run if no Mac/EAS is available. Android builds need the Android SDK + an emulator or device. Forge writes the code + config regardless; it cannot conjure a toolchain that isn't installed.
Fan-out & flow
L2 a single-screen or small app; L3 multi-screen + navigation + offline + native modules + a store build; L4 phased for a large app with several native integrations. Serial: app architecture (navigation + state + data layer) → screens → secure-storage + offline layer → device/emulator QA → release build → store-readiness pass. Parallel: independent screens/features build in parallel once the navigation contract and data layer are fixed (that contract is the integration seam — you are the integration layer).
Domain gates
- Release binary builds and installs + launches on a device or emulator (evidence: build output + a launch screenshot/log), not just Metro/Expo Go.
- No secrets in the JS bundle or committed; tokens in secure store (Keychain/Keystore/SecureStore), not AsyncStorage/SharedPreferences.
- Permissions minimal and justified — iOS usage-description strings present, Android manifest minimal.
- Offline paths work where promised (cached reads, queued writes, no-connection UI) — or offline is honestly declared out of scope.
- Safe-area/notch, keyboard avoidance, orientation, and dark mode (if supported) handled; touch targets adequate (~44pt); long lists use
FlatList/virtualization, not a giantScrollView. - No test/demo/mock data, no debug menu, no
__DEV__shortcut in the release build; release signing configured; app icon + splash + version set.
Ship-readiness (unique)
Release build produced and installed + launched on a real device or emulator (real output attached); secrets confirmed out of the bundle; secure token storage proven; permissions minimal with real rationale strings; offline behaviour verified where promised; icon/splash/version set; no mock data or debug menus in the release artifact. iOS is macOS/Xcode-gated — if no Mac/EAS was available, mark the iOS build not-run honestly rather than implying it shipped. Store-listing assets (screenshots, privacy disclosure, data-safety form) are noted as owner action. Advisory checklist; optionally run security-boss / codex-reviewer on the secret + secure-storage paths — recommended, not a blocker.