---
title: Supported Frameworks
description: AppFlight CLI supports Flutter, React Native bare workflow, and native Android (Kotlin).
---

AppFlight CLI works with Flutter, React Native (bare workflow), and native Android (Kotlin). The backend, storage, and tester distribution are framework-agnostic — the CLI adapts to your project structure based on `projectType` in `appflight.json`.

## Flutter

**Fully supported.**

- Version and build number read from `pubspec.yaml`
- APK paths follow standard Flutter build output: `build/app/outputs/flutter-apk/app-<flavor>-release.apk`
- Works with single-flavor, multi-flavor, or no-flavor setups

```bash
# Flavored Flutter app
appflight init --flavors stage:com.myapp.stage,prod:com.myapp
appflight upload --flavor stage

# No-flavor Flutter app
appflight init
appflight upload
```

## React Native

**Fully supported** (bare workflow only — Expo is not supported).

- Version read from `android/app/build.gradle` (`versionName+versionCode`)
- APK paths follow standard Gradle output: `android/app/build/outputs/apk/<flavor>/release/app-<flavor>-release.apk`
- Works with single-variant and multi-flavor setups

```bash
# Flavored React Native app
appflight init --flavors stage:com.myapp.stage,prod:com.myapp
appflight upload --flavor stage

# No-flavor React Native app
appflight init
appflight upload
```

During `appflight init` you'll be prompted to choose your framework, or skip the prompt with:

```bash
appflight init --project-type react-native
```

### What the CLI reads from Gradle

The CLI parses `android/app/build.gradle` directly — no Gradle execution required.

| Field | Source |
|---|---|
| Version | `versionName` + `versionCode` → `1.2.0+7` |
| APK path | `android/app/build/outputs/apk/…` |

Override the resolved version at upload time with `--version` or `--build-number`.

## Kotlin

**Fully supported** (native Android, no cross-platform layer).

- Version read from `app/build.gradle` (`versionName+versionCode`) — no `android/` wrapper, Gradle files sit at the project root
- APK paths follow standard Gradle output: `app/build/outputs/apk/<flavor>/release/app-<flavor>-release.apk`
- Works with single-variant and multi-flavor setups

```bash
# Flavored native Android app
appflight init --project-type kotlin --flavors stage:com.myapp.stage,prod:com.myapp
appflight upload --flavor stage

# No-flavor native Android app
appflight init --project-type kotlin
appflight upload
```

Build with Gradle from the project root — no `cd android` needed:

```bash
./gradlew assembleStageRelease
```

:::tip Release signing
A fresh Android Studio project has no release `signingConfig` by default — `assembleRelease` then outputs `app-release-unsigned.apk`, which won't match the `apkPath` the CLI expects (`app-release.apk`). Add a `signingConfig` to your `release` build type (the debug keystore is fine for local testing) before running `appflight init`.
:::

### What the CLI reads from Gradle

The CLI parses root `app/build.gradle` directly — no Gradle execution required.

| Field | Source |
|---|---|
| Version | `versionName` + `versionCode` → `1.2.0+7` |
| APK path | `app/build/outputs/apk/…` |

Override the resolved version at upload time with `--version` or `--build-number`.
