AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL unreviewed MIT Self-run

Engineering Mobile App Builder

skill-peterhdd-agent-skills-engineering-mobile-app-builder · by PeterHdd

Build native and cross-platform mobile applications for iOS and Android with optimized performance and platform integration. Use when you need SwiftUI or Jetpack Compose development, React Native or Flutter cross-platform apps, offline-first architecture, biometric authentication, push notifications, deep linking, app startup optimization, or mobile-specific UX patterns and gesture handling.

No reviews yet
0 installs
36 views
0.0% view→install

Install

$ agentstack add skill-peterhdd-agent-skills-engineering-mobile-app-builder

Open-source listing, not yet scanned by AgentStack. Follow the source repository for install instructions.

Security review

⚠ Flagged

1 finding(s); flagged for manual review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures
  • high Destructive filesystem operation.

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Reliability & compatibility

Not yet reviewed
0 installs to date
no reviews yet
6mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Engineering Mobile App Builder? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Mobile Development Guide

Overview

This guide covers native iOS/Android development (SwiftUI, Jetpack Compose) and cross-platform frameworks (React Native, Flutter) with patterns for offline-first architecture, platform integrations, and performance optimization. Use it when choosing a platform strategy, building mobile UI, or integrating device capabilities.

Platform Selection Guide

  • Use native (SwiftUI/Compose) when the app requires deep platform integration (widgets, extensions, AR, custom camera pipelines).
  • Use React Native or Flutter when shipping to both platforms with a small team and the app is primarily data display and forms.
  • For iOS, use SwiftUI with @Observable (iOS 17+) or @StateObject/@ObservedObject (iOS 15+); fall back to UIKit only for unsupported features.
  • For Android, use Jetpack Compose with Hilt for DI and StateFlow for reactive state; avoid XML layouts in new screens.
  • For navigation, use NavigationStack (iOS) or Navigation Compose (Android) with typed routes.

Performance and UX Rules

  • Cold start must be under 2 seconds on mid-range devices; defer initialization not needed for first frame. If cold start exceeds 1.5s, profile with Instruments (iOS) or reportFullyDrawn() (Android) and move heavy work to background.
  • Maintain 60fps scrolling on devices two generations behind current. If frame drops occur: on iOS, check for off-main-thread image decoding and use prefetchDataSource; on Android, enable compositionStrategy = ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed and check for unnecessary recomposition with Layout Inspector.
  • Animations: use SwiftUI .animation() / Compose animateFloatAsState; keep durations 200-350ms. Never animate layout properties (frame size, padding) — animate opacity and offset only.
  • Offline-first: local database (Core Data, Room, SQLite/Drift) as single source of truth, background server sync. If the app has >3 entity types with relationships, use Core Data (iOS) or Room (Android) — never raw SQLite.
  • Profile battery with Xcode Energy Diagnostics or Android Battery Historian; fix any operation keeping CPU awake >2s without user interaction.
  • Batch network requests; use background sessions (URLSession / WorkManager) for large transfers. If payload >1MB, use background transfer; if >10MB, add resumable upload support.
  • Incremental sync with timestamps or change tokens instead of full-collection fetches. If collection has >500 items, paginate sync with cursor; never fetch all.
  • Lazy-load images with caching (Kingfisher/SDWebImage on iOS, Coil on Android); downscale to display size. If list shows >20 images, implement memory cache cap (50MB iOS, 100MB Android) and disk cache cap (200MB).
  • App binary size: target 3 permissions needed, request them progressively as features are used — never batch-request on launch.

Code Examples

See [SwiftUI Guide](references/swiftui.md) for a full product list with NavigationStack, search, pagination, and pull-to-refresh.

See [Jetpack Compose Guide](references/compose.md) for a full product list with Hilt, StateFlow, LazyColumn, and debounced search.

See [React Native Guide](references/react-native.md) for a full product list with FlatList, react-query infinite scrolling, and platform styling.

See [Flutter Guide](references/flutter.md) for a full product list with Riverpod, ListView.builder, debounced search, pagination, and pull-to-refresh.

See [Offline-First Architecture](references/offline-first.md) for offline queue systems (NetInfo + AsyncStorage, Core Data + CloudKit, Room + WorkManager), conflict resolution (LWW, field-level merge, CRDT), and optimistic UI with rollback.

See [Performance Patterns](references/performance.md) for Hermes engine config, FlatList optimization (getItemLayout, windowSize), SwiftUI lazy stacks and image caching, Compose recomposition control with Coil, battery optimization, memory leak prevention, and cold start optimization.

See [State Management](references/state-management.md) for Zustand with MMKV persistence, TanStack Query optimistic mutations, SwiftUI @Observable with environment injection, Compose ViewModel + StateFlow + SavedStateHandle, navigation deep linking, auth state machines, and form validation.

See [Native APIs](references/native-apis.md) for push notifications (APNs, FCM, react-native-firebase), camera/photo (CameraX, AVFoundation, vision-camera), biometric auth (FaceID/TouchID, BiometricPrompt), background tasks (BGTaskScheduler, WorkManager), and non-transactional entitlement architecture notes for app-store subscriptions.

Platform-Specific Gotchas

iOS Background Task Limits

  • BGAppRefreshTask: System grants ~30 seconds of execution. If the task does not call setTaskCompleted within that window, the system kills it and deprioritizes future requests.
  • BGProcessingTask: Up to 3 minutes, but only runs when device is charging and on Wi-Fi. Do not rely on this for time-sensitive sync.
  • After a push notification wakes the app (content-available: 1), you get ~30 seconds. If the work takes longer, start a URLSession background download instead.
  • The system learns user behavior. If the user never opens your app at 8am, your 8am background refresh will not run. Design for missed refreshes — always do a full catch-up sync on foreground.

Android Background Restrictions

  • Doze mode (Android 6+): After screen off + stationary, network access is batched into maintenance windows (~every 15 min, increasing to ~1 hour). WorkManager with NetworkType.CONNECTED constraint will defer until the next window. For urgent messages, use FCM high-priority messages (limited to ~10/day before throttled).
  • App Standby Buckets (Android 9+): Apps are ranked Active → Working Set → Frequent → Rare → Restricted. Rare/Restricted apps get severely limited jobs and alarms. If your app is in Restricted bucket, WorkManager periodic work may run only once per 24 hours.
  • Exact alarms (Android 12+): setExactAndAllowWhileIdle() requires SCHEDULE_EXACT_ALARM permission. Users can revoke it in Settings. Always check canScheduleExactAlarms() before scheduling and fall back to inexact.
  • Foreground service types (Android 14+): Must declare foregroundServiceType in manifest. Types: camera, location, mediaPlayback, dataSync, etc. Using wrong type → crash. dataSync type is limited to 6 hours.

Flutter-Specific Gotchas

  • const constructors: Always use const for stateless widgets and unchanging widget subtrees. Without const, Flutter rebuilds the entire subtree on parent rebuild. This is the #1 Flutter performance issue.
  • Keys: Use ValueKey on list items when the list can reorder, insert, or delete. Without keys, Flutter reuses state incorrectly — user types in TextField A, deletes item, and the text appears in item B.
  • Platform channels: Calls between Dart and native (iOS/Android) are async and serialized. If you call a platform channel in a tight loop (>100 calls/sec), batch the data into a single call. Use BasicMessageChannel with binary codec for large payloads.
  • Isolates: Dart is single-threaded. For CPU work >16ms (JSON parsing large responses, image processing), use Isolate.run() (Dart 2.19+) or compute(). Never parse >100KB JSON on the main isolate.
  • Image caching: Flutter's default Image widget caches decoded images in memory with no limit. For lists with >50 images, use cached_network_image with memCacheHeight/memCacheWidth to downscale, or the memory will grow unbounded.
  • State restoration: On Android, the system kills background apps aggressively. Use RestorationMixin or persist critical state to disk. If the user fills a 10-field form, switches to another app, and comes back to a blank form — that is a bug.

Compose-Specific Gotchas

  • Recomposition: Any lambda that captures a mutable value triggers recomposition of its parent. Pass remember-ed lambdas or use derivedStateOf for expensive computations. Use Layout Inspector > "Show Recomposition Counts" to find hot spots.
  • Stability: Compose skips recomposition for @Stable or @Immutable types. If your data class uses List (unstable), Compose recomposes every time. Use kotlinx.collections.immutable.ImmutableList or annotate with @Immutable if you guarantee immutability.
  • LazyColumn item keys: Always provide key in items(key = { it.id }). Without keys, scroll position breaks on list mutations and animations fail.

Offline Sync Decision Rules

Conflict Resolution Strategy

  • Last-Write-Wins (LWW): Use when data is user-owned and rarely edited concurrently (user profile, settings, personal notes). Simple: compare timestamps, latest wins. Risk: silent data loss if two devices edit simultaneously.
  • Field-level merge: Use when different fields of the same record may be edited on different devices (e.g., user edits name on phone, email on tablet). Merge non-conflicting field changes, flag conflicting fields for manual resolution. Requires tracking per-field timestamps.
  • Operational Transform / CRDT: Use only for real-time collaborative editing (shared documents, collaborative whiteboards). Complex to implement — use a library (Yjs, Automerge). Never build custom OT/CRDT.
  • Queue-and-retry: Use for write-only operations (form submissions, analytics events, chat messages). Queue locally, send when online, retry with idempotency keys. No conflict possible because each operation is independent.

Sync Architecture Decision Rules

  • If the app has 1% at any stage, pause and investigate.

Anti-Patterns

  • Never use @ObservedObject for state owned by the current view — use @StateObject (iOS 15) or @State with @Observable (iOS 17+). @ObservedObject is for injected dependencies only.
  • Never use mutableStateOf outside a ViewModel in Compose — all mutable state lives in ViewModels, UI observes via collectAsStateWithLifecycle().
  • Never call setState on a disposed widget in Flutter — always check mounted before async state updates. In Riverpod, use ref.onDispose() to cancel async work.
  • Never use FlatList without keyExtractor and getItemLayout in React Native — without these, scrolling performance degrades dramatically on lists >50 items.
  • Never store navigation state in a global store — use the platform navigation stack. Global nav state causes back-button bugs and deep link failures.
  • Never block the main thread with synchronous database reads — use withContext(Dispatchers.IO) (Android) / background actors (iOS) / InteractionManager.runAfterInteractions (React Native) / Isolate.run() (Flutter).
  • Never parse large JSON (>100KB) on the main thread in Flutter — use compute() or Isolate.run(). On Android, never do network or disk I/O on the main thread — StrictMode will catch this in debug builds.
  • Never use platform-specific code without a fallback. If a plugin is iOS-only, the Android build must not crash — it should degrade gracefully or show "not available on this platform."

Workflow

Step 1: Platform Strategy and Setup

  • Choose native vs cross-platform: if app needs AR, custom camera, or widgets, go native. If app is data display + forms with 80% coverage.
  • Set up Fastlane (iOS) or Gradle Play Publisher (Android) for automated store submission.

Self-Verification Protocol

After completing any mobile implementation, verify before submitting for review:

  • Run the app on a real device (not just simulator). Simulators hide performance, memory, and gesture issues.
  • Test the core flow offline: enable airplane mode, perform the action, re-enable network, verify sync. If the app crashes or loses data offline, it is not ready.
  • Profile memory on a mid-range device. If peak memory exceeds 200MB, investigate before shipping.
  • Measure cold start time on the oldest supported device. If >2s, defer initialization until after first frame.
  • Verify all touch targets are >=44pt (iOS) / >=48dp (Android) by tapping every interactive element with a finger, not a mouse cursor.
  • Check Dark Mode on every screen. If any text is unreadable or any element is invisible, fix before merge.
  • Test with Dynamic Type (iOS) / Font Scale 200% (Android). If text truncates or overlaps, fix the layout.
  • Run the app with VoiceOver (iOS) / TalkBack (Android) on the core flow. Every interactive element must be announced meaningfully.
  • Check that no sensitive data (tokens, passwords, PII) appears in logs. Run adb logcat (Android) or Console.app (iOS) during the flow.

Failure Recovery

  • App crashes on launch: Check crash log for the exact line. Common causes: force-unwrapped nil (Swift), uninitialized lateinit (Kotlin), missing native module (React Native). If the crash is in a third-party library, pin the previous version and file an issue.
  • Build fails after Xcode/Gradle update: Clean derived data (rm -rf ~/Library/Developer/Xcode/DerivedData) or Gradle cache (./gradlew clean). If still failing, check release notes for breaking changes in build tools. Pin the toolchain version in the project until the issue is resolved.
  • UI renders differently on device vs simulator: The simulator uses the Mac GPU. Test on a real device. For layout issues, check for hardcoded pixel values (use pt/dp instead) and safe area insets.
  • Performance drops after adding a feature: Profile with Instruments (iOS) or Android Studio Profiler. Check for: main thread blocking, excessive recomposition/re-renders, large image loading without caching, or leaked subscriptions/observers.
  • Push notifications not arriving: Verify: (1) valid APNs/FCM token, (2) correct bundle ID/package name, (3) certificate/key not expired, (4) device not in low-power mode suppressing background activity. Test with a manual push via curl to APNs/FCM before debugging app code.
  • App rejected by App Store / Play Store: Read the rejection reason exactly. Common: missing privacy policy URL, incomplete App Privacy details (iOS), missing data safety form (Android), or background location usage without justification. Fix the metadata — do not guess.

Existing App Orientation

When taking over or joining an existing mobile project:

  1. Build and run (15 min) — Clone, install deps, build, run on a real device. If it fails, fix the build first.
  2. Identify the architecture pattern (10 min) — MVC, MVVM, MVI, or unstructured? Check: where does state live? How does data flow from API to UI?
  3. Map the navigation graph (10 min) — List all screens and how they connect. Check for deep link handlers. Note any navigation library in use.
  4. Check the dependency list (5 min) — Podfile/SPM (iOS), build.gradle (Android), package.json (React Native). Flag outdated or abandoned dependencies.
  5. Run existing tests (5 min) — Note coverage, test types, and which flows are untested.
  6. Check for platform-specific debt (5 min) — Deprecated APIs (check Xcode warnings, Android lint), missing permissions declarations, hardcoded strings (localization readiness).
  7. Profile the app (10 min) — Cold start time, memory usage, scroll performance on the heaviest list screen. These numbers are your baseline.

Scripts

scripts/check_app_size.sh

Analyze a mobile app build output directory for size issues. Takes a build output directory as argument, finds app binaries/bundles (.app, .apk, .aab, .ipa), reports total size, largest files, and asset breakdown by category. Warns if total exceeds common thresholds (50MB for iOS, 150MB for Android).

scripts/check_app_size.sh ./build/outputs/apk/release
scripts/check_app_size.sh --threshold-ios 40 --top-files 10 ./DerivedData/Build/Products/Release-iphoneos

scripts/check_permissions.py

Extract and audit permissions from AndroidManifest.xml or Info.plist. Identifies requested permissions, flags potentially dangerous ones (CAMERA, LOCAT

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.