flutter-mobile-design
A comprehensive guide for building, designing, and deploying enterprise-grade Flutter mobile applications.
Install
mkdir -p .claude/skills/flutter-mobile-design && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/13717" && unzip -o skill.zip -d .claude/skills/flutter-mobile-design && rm skill.zipInstalls to .claude/skills/flutter-mobile-design
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Comprehensive reference for Flutter mobile app development and UI/UX design. Covers architecture, design patterns, component creation, animations, state management, Firebase integration, flavor configuration, localization, and deployment.Key capabilities
- →Define a project structure for Flutter applications
- →Organize code into layered architecture components
- →Implement state management using ChangeNotifier classes
- →Configure Firebase integration within the application
- →Manage application themes and localization
- →Structure tests for unit, widget, and end-to-end scenarios
How it works
The skill provides a universal reference for building Flutter mobile applications by outlining a recommended project structure and layered architecture. It defines responsibilities for screens, widgets, providers, services, models, and core components.
Inputs & outputs
When to use flutter-mobile-design
- →Set up Flutter architecture
- →Implement state management
- →Design UI components
- →Configure Firebase in Flutter
About this skill
Flutter Mobile Design Skill
Universal reference for building premium Flutter mobile applications. Project-agnostic — use with any Flutter + Firebase project.
1. Recommended Project Structure
{project_root}/
├── lib/
│ ├── main.dart # App entry point
│ ├── main_{flavor}.dart # Flavor-specific entry points (if flavors used)
│ ├── app.dart # MaterialApp / root widget
│ ├── core/
│ │ ├── config/
│ │ │ ├── app_config.dart # Runtime config (env, URLs, feature flags)
│ │ │ ├── firebase_config.dart # Firebase initialization
│ │ │ └── flavor_config.dart # Flavor enum, branding tokens
│ │ ├── theme/
│ │ │ ├── app_colors.dart # Color tokens
│ │ │ ├── app_typography.dart # Text styles
│ │ │ └── app_spacing.dart # Spacing, radius, padding constants
│ │ ├── session/
│ │ │ └── session_initializer.dart
│ │ └── constants.dart # App-wide constants
│ ├── models/ # Data classes (fromJson/toJson)
│ ├── services/ # API calls, Firebase ops, external integrations
│ ├── providers/ # ChangeNotifier state management classes
│ ├── router/
│ │ └── app_router.dart # GoRouter / Navigator 2.0 config
│ ├── screens/ # Full-page views (one per screen)
│ ├── widgets/ # Reusable UI components
│ ├── l10n/ # ARB localization source files
│ │ ├── app_en.arb
│ │ └── app_es.arb
│ └── generated/ # ⚠️ Auto-generated (NEVER edit manually)
│ └── l10n/
├── assets/
│ ├── images/
│ ├── videos/
│ └── animations/ # Lottie JSON files
├── android/
│ └── app/src/{flavor}/ # Flavor-specific Android resources
├── ios/
│ ├── Runner/
│ └── config/{flavor}/ # Flavor-specific iOS configs
├── test/ # Unit & widget tests
├── integration_test/ # E2E tests
├── pubspec.yaml
└── analysis_options.yaml
2. Layered Architecture
2.1 Layer Responsibilities
┌─────────────────────────────────────────────────────┐
│ SCREENS (Pages) │
│ Full-page views. Compose widgets, consume providers.│
│ One file per screen. Never contains business logic. │
├─────────────────────────────────────────────────────┤
│ WIDGETS (Components) │
│ Reusable UI. Stateless preferred. Accept data via │
│ constructor. No business logic, no service calls. │
├─────────────────────────────────────────────────────┤
│ PROVIDERS (State / Business Logic) │
│ ChangeNotifier classes. Call services, expose state │
│ to UI. Handle loading/error/data states. │
├─────────────────────────────────────────────────────┤
│ SERVICES (Data Layer) │
│ Firebase, REST APIs, local storage. Return raw data.│
│ No UI awareness. Stateless static methods or │
│ singleton instances. │
├─────────────────────────────────────────────────────┤
│ MODELS (Data Structures) │
│ Dart classes with fromJson/toJson/fromFirestore. │
│ Immutable when possible. No logic beyond parsing. │
├─────────────────────────────────────────────────────┤
│ CORE (Infrastructure) │
│ Config, theme, session, constants. Shared across │
│ all layers. │
└─────────────────────────────────────────────────────┘
2.2 Dependency Flow
Screens → Widgets
Screens → Providers (via Consumer/context.read)
Providers → Services
Services → Models
Core ← used by all layers
Rules:
- Screens NEVER call services directly
- Widgets NEVER access providers (receive data via constructor)
- Providers NEVER import UI classes
- Services NEVER import Flutter material
2.3 Clean Architecture — Gradual Refactor Levels
Level 1 (Starting point): Screens + Providers + Services + Models. Good enough for most apps < 20 screens.
Level 2 (Moderate complexity): Add a repositories/ layer between providers and services for data source abstraction (local cache + remote).
// lib/repositories/investment_repository.dart
class InvestmentRepository {
final InvestmentRemoteService _remote;
final InvestmentCacheService _cache;
Future<List<Investment>> getAll({bool forceRefresh = false}) async {
if (!forceRefresh) {
final cached = await _cache.getAll();
if (cached.isNotEmpty) return cached;
}
final data = await _remote.fetchAll();
await _cache.saveAll(data);
return data;
}
}
Level 3 (Large apps, 30+ screens): Add use_cases/ (interactors) between providers and repositories to isolate business operations.
// lib/use_cases/calculate_returns.dart
class CalculateReturns {
final InvestmentRepository _repo;
Future<ReturnsSummary> execute(String investorId) async {
final investments = await _repo.getByInvestor(investorId);
// Business logic here
return ReturnsSummary.fromInvestments(investments);
}
}
3. State Management (Provider)
3.1 Provider Template
class FeatureProvider extends ChangeNotifier {
List<Item> _items = [];
bool _isLoading = false;
String? _error;
// Getters — never expose internal state directly
List<Item> get items => List.unmodifiable(_items);
bool get isLoading => _isLoading;
String? get error => _error;
bool get hasData => _items.isNotEmpty;
Future<void> load() async {
_isLoading = true;
_error = null;
notifyListeners();
try {
_items = await FeatureService.getAll();
} catch (e) {
_error = e.toString();
} finally {
_isLoading = false;
notifyListeners();
}
}
void clear() {
_items = [];
_error = null;
notifyListeners();
}
}
3.2 Provider Registration
// In main.dart or app.dart
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => AuthProvider()),
ChangeNotifierProvider(create: (_) => InvestmentProvider()),
// Add providers as features grow
],
child: const MyApp(),
)
3.3 Consuming in UI
// ✅ Consumer — rebuilds only this subtree
Consumer<FeatureProvider>(
builder: (context, provider, child) {
if (provider.isLoading) return const LoadingSkeleton();
if (provider.error != null) return ErrorState(message: provider.error!);
if (!provider.hasData) return const EmptyState();
return ItemList(items: provider.items);
},
)
// ✅ context.read — for one-time actions (button taps)
ElevatedButton(
onPressed: () => context.read<FeatureProvider>().load(),
child: const Text('Refresh'),
)
// ❌ NEVER use context.watch in callbacks
// ❌ NEVER use setState for shared state
4. Flavor / Environment Configuration
4.1 Flavor Enum
// lib/core/config/flavor_config.dart
enum AppFlavor {
development,
staging,
production;
// Per-flavor values
String get firebaseFunctionsBaseUrl => switch (this) {
development => 'http://localhost:5001/{project_id}/us-central1',
staging => 'https://us-central1-{staging_project_id}.cloudfunctions.net',
production => 'https://us-central1-{prod_project_id}.cloudfunctions.net',
};
String get appName => switch (this) {
development => '{App Name} DEV',
staging => '{App Name} STG',
production => '{App Name}',
};
}
4.2 Client/Brand Flavor (Multi-tenant)
For apps serving multiple clients with different branding:
// lib/core/config/brand_config.dart
enum AppBrand {
brandA,
brandB;
// These values change per client
String get displayName => switch (this) {
brandA => 'Brand A Name',
brandB => 'Brand B Name',
};
Color get primaryColor => switch (this) {
brandA => const Color(0xFF1A237E),
brandB => const Color(0xFF004D40),
};
Color get accentColor => switch (this) {
brandA => const Color(0xFFFFB300),
brandB => const Color(0xFF00BFA5),
};
String get logoAsset => switch (this) {
brandA => 'assets/images/logo_brand_a.png',
brandB => 'assets/images/logo_brand_b.png',
};
String get firebaseProjectId => switch (this) {
brandA => '{firebase_project_id_a}',
brandB => '{firebase_project_id_b}',
};
}
4.3 Runtime Configuration with --dart-define
// lib/core/config/app_config.dart
class AppConfig {
static late final AppFlavor flavor;
static late final AppBrand brand;
static void initialize() {
// Read from --dart-define at compile time
const flavorStr = String.fromEnvironment('FLAVOR', defaultValue: 'development');
const brandStr = String.fromEnvironment('BRAND', defaultValue: 'brandA');
flavor = AppFlavor.values.firstWhere(
(f) => f.name == flavorStr,
orElse: () => AppFlavor.development,
);
brand = AppBrand.values.firstWhere(
(b) => b.name == brandStr,
orElse: () => AppBrand.brandA,
);
}
static String get functionsBaseUrl => flavor.firebaseFunctionsBaseUrl;
static String get appName => '${brand.displayName}${flavor != AppFlavor.production ? ' (${flavor.name.toUpperCase()})' : ''}';
}
4.4 Running with Flavors
# Development + Brand A
flutter run --dart-define=FLAVOR=development --dart-define=BRAND=brandA
# Production + Brand B
flutter run --release --dart-define=FLAVOR=production --dart-define=BRAND=brandB
# Build APK for specific flavor
flutter build apk --release \
--dart-define=FLAVOR=production \
--dart-define=BRAND=brandB
4.5 Flavor-Specific Entry Points (Alternative)
// lib/main_brand_a.dart
void main() {
AppConfig.initializeWith(brand: AppBrand.brandA, flavor: AppFlavor.production);
runApp(const MyApp());
}
// lib/main_brand_b.dart
void main() {
AppConfig.initializeWith(b
---
*Content truncated.*
When not to use it
- →When the project does not use Flutter
- →When the project does not use Firebase
- →When not building mobile applications
Limitations
- →The skill is project-agnostic and provides general guidance, not specific implementation code.
- →It focuses on Flutter and Firebase projects.
- →The skill does not provide specific versions for dependencies, requiring manual verification.
How it compares
This approach standardizes project organization and dependency flow, unlike ad-hoc development that can lead to inconsistent structures and tangled dependencies.
Compared to similar skills
flutter-mobile-design side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| flutter-mobile-design (this skill) | 0 | 2mo | Review | Intermediate |
| mobile-design | 149 | 4mo | Review | Intermediate |
| figma-import | 0 | 3mo | No flags | Advanced |
| iOS Animation Graphics Skill | 0 | 5mo | No flags | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
mobile-design
sickn33
Mobile-first design and engineering doctrine for iOS and Android apps. Covers touch interaction, performance, platform conventions, offline behavior, and mobile-specific decision-making. Teaches principles and constraints, not fixed layouts. Use for React Native, Flutter, or native mobile apps.
figma-import
gskinnerTeam
Translates Figma designs into production-ready Flutter code. Use when: importing, implementing, or building UI from a Figma design, link, or node; user mentions 'implement design', 'generate code', 'implement component', provides Figma URLs, or asks to build widgets matching Figma specs. Covers the
iOS Animation Graphics Skill
bsreeram08
Creating animations and graphics using SwiftUI Canvas, Core Animation, and Lottie integration for engaging iOS app experiences.
reduce-motion
almasumdev
Detecting and honoring the user's reduce motion preference on iOS, Android, Flutter, and React Native. Use this when building transitions, parallax, hero animations, or autoplay.
flutter-development
aj-geddes
Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.
mobile-android-design
wshobson
Master Material Design 3 and Jetpack Compose patterns for building native Android apps. Use when designing Android interfaces, implementing Compose UI, or following Google's Material Design guidelines.