# Mobile Tech Stack Selection

> Decision framework for choosing between native iOS/Android, Flutter, React Native, and Kotlin Multiplatform for a new or migrating mobile project. Use when the stack is undecided or being revisited.

- Skill: `almasumdev/mobile-tech-stack-selection` (Agent Skill)
- Install (CLI): `npx skillmds@latest add almasumdev/mobile-tech-stack-selection`
- Raw SKILL.md: https://api.skillmd.com/api/skills/almasumdev/mobile-tech-stack-selection/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: almasumdev (https://skillmd.com/u/almasumdev)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/almasumdev/mobile-tech-stack-selection

---


# Mobile Tech Stack Selection

## Instructions

Stack choice is a one-way door for most of the codebase. Use an explicit decision framework rather than taste. The goal is to pick the stack whose strengths match the project's constraints.

### 1. Candidate Stacks (2026 baseline)

- **Native iOS** -- Swift 5.9+, SwiftUI + UIKit interop, Xcode 15+.
- **Native Android** -- Kotlin 1.9+, Jetpack Compose + View interop, AGP 8+.
- **Flutter** -- Dart 3.4+, Flutter 3.22+, Impeller renderer.
- **React Native** -- 0.74+ with New Architecture (Fabric + TurboModules), usually via Expo SDK 51+.
- **Kotlin Multiplatform (KMP)** -- Kotlin 1.9+, shared business logic, Compose Multiplatform for UI when desired.
- **Native + KMP shared logic** -- SwiftUI + Compose with a shared Kotlin domain module.

### 2. Decision Dimensions

Score each stack against the project on these dimensions:

| Dimension | Weight signal |
| --- | --- |
| Time-to-first-build on both platforms | Small team, tight deadline -> high |
| Platform API reach (Bluetooth, ARKit, CameraX, HealthKit) | Deep native integration -> native wins |
| UI fidelity with platform conventions | Banking, productivity apps -> native or KMP+native UI |
| Shared business logic reuse | Complex domain, multiple clients -> KMP shines |
| Hot reload / iteration speed | Rapid design iteration -> Flutter, RN |
| Binary size sensitivity | Emerging markets, tight APK -> native |
| Team skillset | Existing Kotlin team -> KMP/Android; web team -> RN |
| Hiring pool in your geography | Plain Android/iOS typically deepest |
| Long-term maintenance risk | Stack longevity, vendor neutrality |

### 3. Default Recommendations

- **Two engineers, consumer content app, need both platforms fast:** Flutter or React Native.
- **Existing web/React team, content-heavy app with some native integrations:** React Native with Expo.
- **Consumer app with heavy native surface (AR, ML, camera) and bespoke UI:** native, possibly with KMP for shared logic.
- **Fintech / regulated app needing exact platform behavior:** native. Treat cross-platform as a last resort.
- **Productivity app with complex domain rules and multiple clients (mobile + desktop):** KMP core + native UI, or Compose Multiplatform.
- **Internal/enterprise tool with low UX bar, short TTM:** React Native or Flutter.

### 4. Cross-Platform Parallels

The same "show a user name" problem in each stack, so the agent can reason about equivalence:

```swift
// Swift / SwiftUI
struct UserView: View {
    let name: String
    var body: some View { Text(name).font(.headline) }
}
```

```kotlin
// Kotlin / Jetpack Compose
@Composable
fun UserView(name: String) {
    Text(name, style = MaterialTheme.typography.titleMedium)
}
```

```dart
// Dart / Flutter
class UserView extends StatelessWidget {
  const UserView({super.key, required this.name});
  final String name;
  @override
  Widget build(BuildContext context) =>
      Text(name, style: Theme.of(context).textTheme.titleMedium);
}
```

```tsx
// TypeScript / React Native
export function UserView({ name }: { name: string }) {
  return <Text style={{ fontSize: 20, fontWeight: '600' }}>{name}</Text>;
}
```

### 5. Decision Record Template

Write the outcome as an ADR. Do not let it live in Slack.

```markdown
# ADR-001: Mobile Stack

## Status
Accepted 2026-04-19.

## Context
- Team: 3 engineers (2 Android/Kotlin, 1 iOS/Swift).
- Product: B2C fitness tracker, heavy HealthKit/Google Fit integration.
- Constraints: 4-month MVP, both platforms at launch.

## Options considered
1. Native iOS + Native Android
2. Flutter
3. React Native (Expo)
4. KMP + native UI

## Decision
KMP shared domain + native UI on each platform.

## Consequences
+ Native HealthKit / Health Connect access with no plugin lag.
+ Domain rules written once.
- Initial setup cost; KMP toolchain maturity on iOS requires attention.
- Hiring for iOS + KMP is narrower than pure iOS.
```

### 6. Review Triggers

Revisit the stack decision when:

- The primary use case shifts (e.g., adding AR, video editing).
- Binary size or startup time blocks a launch gate.
- Two consecutive OS releases require workarounds in the framework.
- The team composition changes materially.

### 7. Anti-Patterns to Refuse

- "React Native is cheaper" without accounting for native module work.
- "We will adopt KMP incrementally starting with UI." UI is the hardest KMP surface; start with networking/domain.
- "Just use whatever we used last project." Re-score against this project.
- "Flutter cannot do X" without citing a current source; capabilities move quickly.

## Checklist

- [ ] Decision dimensions are scored per candidate stack.
- [ ] Team skillset and hiring pool are explicit in the ADR.
- [ ] Native API reach is validated for the top five integrations.
- [ ] An ADR exists in the repo and is linked from the README.
- [ ] Review triggers are written down so the decision is not sticky by accident.
- [ ] A prototype of the single riskiest feature is built in the candidate stack before committing.

