impulse-mobile
Guides you to build mobile apps the right way, whether using Flutter, React Native, or native code.
Installation
Paste this into Claude Code, Cursor, or any agent that can run commands.
SKILL.mdShow the author's original SKILL.md
--- name: impulse-mobile description: > Mobile engineering — Flutter-first (owner's primary), React Native, native SwiftUI/Kotlin, WebView wrappers. Anti-overengineering ladder for platform choice, day-one mobile baseline (crash reporting, release signing, dispose discipline, network timeouts), and the mobile-specific bug catalog. Triggers: "/impulse-mobile", "flutter", "react native", "swiftui", "kotlin android", "мобилка", "мобильное приложение", "флаттер", "андроид", "widget", "riverpod", "flatlist", "push notifications", "deep link", "webview", "app store", "offline-first". --- # impulse-mobile Mobile counterpart to impulse-backend/impulse-frontend. Same stance: the plainest thing that ships, a day-one baseline that's never skipped, ceiling markers for deferred scaling. Flutter is the owner's primary — deepest coverage there. Content synthesized from openly-licensed sources (see Lineage in README); native Apple docs are orientation-only (proprietary). ## Platform-choice ladder — rungs are IDs `MO-LD1`–`MO-LD4` Stop at the first that holds: 1. **Cross-platform (Flutter)** unless a reason below forces otherwise — one codebase, two platforms. 2. **React Native** if the team/ecosystem is already React-native and the app is React-shaped. 3. **Drop to native for ONE feature** via platform channel / native module — not a full native rewrite — when it needs OS-level fidelity, a tiny system-utility binary, or deep OEM/hardware API access a bridge can't reach cleanly. 4. **Full native (SwiftUI/Kotlin)** only when most of the app is that one feature. Not a rung, a separate axis — shared-core threshold: - Trigger: the same **nontrivial** logic must run identically on 3+ platforms (mobile + desktop + web/CLI). - Action: put it in a shared Rust core, give each platform a thin UI layer instead of N reimplementations. - Bindings: `flutter_rust_bridge` (Dart), `uniffi` (Swift/Kotlin), `napi` (Electron/Node), `wasm-pack` (web). - Crypto is almost always over this threshold — divergent implementations cost user data, not just dev time. - Below the threshold (2 platforms, or logic that's genuinely simple): keep separate codebases; reach for a Rust core only once the trigger above is met. ## Day-one mobile baseline — never skipped IDs `MO-BL01`–`MO-BL08` in listed order; [`shared/rule-spine.md`](../../shared/rule-spine.md) maps each to the impulse-review tag that catches it. - Crash reporting wired (Sentry/Crashlytics) from build #1 - Release signing + auto-incremented build number, both done by CI only - Timeout on every network call (same rule as impulse-backend baseline) - **Dispose discipline:** every subscription/controller/listener/observer opened has a paired teardown — the #1 mobile leak (`hardening-mobile.md`) - Phased rollout (1%→5%→20%→50%→100%) with a crash-rate halt threshold - No secret in the app binary (see cross-cutting.md — it's public) - **Feature flags wired from release #1** — a mobile rollout can't be redeployed away: a user already on a broken build stays broken until the next release clears store review. A flag is the only kill-switch that reaches them (GrowthBook is a common choice). - **Toolchain version pinned in-repo** — fvm + `.fvmrc` for Flutter. One line, and it removes the entire "builds on my machine, not in CI" class of drift. ## References — load on demand | File | Covers | Load when | |---|---|---| | references/flutter.md | state-mgmt choice, rebuild perf, BuildContext-async-gap, auto_route/go_router, pigeon platform channels, isolates, dispose, fvm, localization codegen | any Flutter work | | references/react-native.md | New Arch/Expo choice, FlatList perf, Expo Router, state, bridge/listener leaks | any React Native work | | references/native.md | native-vs-cross-platform decision, SwiftUI @Observable state, Kotlin coroutines/Compose, dropping to native | native code or a platform channel | | references/cross-cutting.md | secrets-in-binary, deep linking, WebView security, offline-first sync, push, release discipline | any app (all platforms) | | references/hardening-mobile.md | the mobile AI-typical bug catalog: leaks, main-thread blocking, list perf, lifecycle, Keychain/biometric misuse | reviewing mobile code | | references/app-store.md | App Store + Play Store rejection causes, submission API gotchas, ASO, ATT/SKAdNetwork/AdAttributionKit attribution, guideline-drift-detection technique | submission prep, store metadata, attribution/ad-SDK wiring | | references/android-deps.md | Gradle/version-catalog bump procedure: coupled-version detection, JitPack blind spot, Kotlin/AGP/SDK-level never-auto-safe rule, verify-by-build-not-resolve | bumping Android dependency versions | | references/apk-security-review.md | post-build APK/AAB forensic security pass: toolchain, Flutter-`libapp.so` secrets trap, critical-blocker list, severity scoring, never-auto-edit list | reviewing a built Android artifact before release | | references/audits.md | OWASP Mobile Top 10 checklist, Flutter localization audit (ICU plurals/RTL), Flutter/pub dependency audit (discontinued/license/pinning) | a standalone security/i18n/dependency audit pass, not per-PR review | | references/kmp.md | Kotlin Multiplatform: expect/actual vs interface+DI, Android-to-KMP incremental migration order and anti-patterns | adding an iOS target to an existing native Android app via KMP | | references/flutter-games.md | Flutter Flame 2D games: dt-clamping, collision, hybrid overlay UI, monetization + kids-safety checklist | building a Flame/game-loop project, not general app UI | | [../../shared/rule-spine.md](../../shared/rule-spine.md) | builder↔review crosswalk: rule ID → detector → review tag | adding/renumbering a baseline item or ladder rung, or asking which review tag catches one | | [../../shared/context7.md](../../shared/context7.md) | Flutter/React Native/SwiftUI/Kotlin API syntax before writing against it — New Arch/Expo/Compose move fast | unfamiliar SDK API or a version-pinned mobile dep | ## Boundaries - Backend the app talks to → impulse-backend; auth/token handling → impulse-security (mobile-specific: secret-in-binary rule in cross-cutting.md). - Web frontend → impulse-frontend (no ai-tells/register model transfers to mobile — different paradigm). - "stop impulse" / "normal mode": revert to default behavior. ## Before you finish - Does every `MO-BL01`–`MO-BL08` baseline item still hold for what you shipped, not just the feature the user asked for? - Did you stop at the first platform-choice rung that holds, instead of defaulting to native or a bridge? - Is dispose discipline (paired teardown for every subscription/controller/listener/observer) actually in the diff? - If you crossed the shared-core threshold, did you use the Rust-core path instead of a fourth reimplementation? ## Recap The day-one mobile baseline is never skipped — it is the one rule everything else in this file defers to.
Ships with 11 supporting files:
- references/android-deps.md
- references/apk-security-review.md
- references/app-store.md
- references/audits.md
- references/cross-cutting.md
- references/flutter-games.md
- references/flutter.md
- references/hardening-mobile.md
- references/kmp.md
- references/native.md
- references/react-native.md
Mirrored from the author's public source. Install counts from the open skills registry.