Documentation

Installation

Add the dependencies a Flutter AppMint app needs to pubspec.yaml.

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:3300 for local dev, https://appengine.appmint.io for 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.