A Flutter AppMint app pulls a small set of well-known Pub.dev packages — there is no first-party SDK to install. Pick the dependency set that matches what your app does. Consumer apps (storefront, events, errands) need a smaller surface than admin apps (offline cache, biometrics, BLoC).
Prerequisites
- Flutter SDK 3.5 or higher (Dart 3.5+).
- Xcode 15+ for iOS builds, Android Studio with API 33+ for Android.
- An AppEngine endpoint to talk to:
http://localhost:3300for local dev,https://appengine.appmint.iofor prod.
Verify your toolchain:
flutter --version
flutter doctor
Dependency sets
Two profiles cover every reference app. Start with Consumer for any customer-facing app; switch to Admin if you need offline cache, biometrics, or BLoC state.
name: my_appmint_app
description: Customer-facing app on AppMint
publish_to: 'none'
version: 1.0.0+1
environment:
sdk: '>=3.5.0 \<4.0.0'
dependencies:
flutter:
sdk: flutter
# Network
http: ^1.2.1
# State
provider: ^6.1.2
# Auth & storage
jwt_decoder: ^2.0.1
flutter_secure_storage: ^10.0.0
shared_preferences: ^2.2.3
# UI helpers
cached_network_image: ^3.3.1
cupertino_icons: ^1.0.8
# Realtime (chat, feed)
socket_io_client: ^3.0.0
# Utilities
intl: ^0.20.2
connectivity_plus: ^6.0.5
After editing pubspec.yaml, fetch the packages:
flutter pub get
If you added Hive models, run the generator:
dart run build_runner build --delete-conflicting-outputs
Platform setup
A few packages need platform-specific config.
iOS
flutter_secure_storage works out of the box, but Stripe and local_auth need keychain entitlements. In ios/Runner/Info.plist, add:
<key>NSFaceIDUsageDescription</key>
<string>Use Face ID to sign in</string>
<key>NSCameraUsageDescription</key>
<string>Used for product photos and document capture</string>
If your app embeds Stripe (see the checkout recipe), set the iOS deployment target to 13.0 in ios/Podfile:
platform :ios, '13.0'
Android
In android/app/build.gradle, set minSdkVersion 23 (required by flutter_secure_storage) and targetSdkVersion 34. Add internet permission to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
Verify the setup
Create a smoke-test screen that hits AppEngine's public health endpoint to confirm networking is wired up.
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class HealthScreen extends StatefulWidget {
const HealthScreen({super.key});
@override
State<HealthScreen> createState() => _HealthScreenState();
}
class _HealthScreenState extends State<HealthScreen> {
String _status = 'pinging...';
@override
void initState() {
super.initState();
_ping();
}
Future<void> _ping() async {
try {
final r = await http.get(Uri.parse('http://localhost:3300/health'));
setState(() => _status = 'HTTP ${r.statusCode}');
} catch (e) {
setState(() => _status = 'error: $e');
}
}
@override
Widget build(BuildContext context) =>
Scaffold(body: Center(child: Text(_status)));
}
If you see HTTP 200, you are ready to wire up real auth — head to Configuration next.
On iOS simulator, localhost works. On Android emulator, use http://10.0.2.2:3300 instead — that's the loopback address for the host machine. On physical devices, use the host's LAN IP and make sure your firewall allows it.