mobile-best-practices 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -0
- package/assets/data/anti-patterns.csv +114 -0
- package/assets/data/architectures.csv +50 -0
- package/assets/data/code-snippets.csv +80 -0
- package/assets/data/gradle-deps.csv +79 -0
- package/assets/data/libraries.csv +102 -0
- package/assets/data/performance.csv +229 -0
- package/assets/data/platforms/android.csv +247 -0
- package/assets/data/platforms/flutter.csv +55 -0
- package/assets/data/platforms/ios.csv +61 -0
- package/assets/data/platforms/react-native.csv +56 -0
- package/assets/data/project-templates.csv +19 -0
- package/assets/data/reasoning-rules.csv +57 -0
- package/assets/data/security.csv +438 -0
- package/assets/data/testing.csv +74 -0
- package/assets/data/ui-patterns.csv +92 -0
- package/assets/references/CHECKLIST.md +49 -0
- package/assets/references/CODE-RULES.md +123 -0
- package/assets/scripts/__pycache__/core.cpython-314.pyc +0 -0
- package/assets/scripts/core.py +432 -0
- package/assets/scripts/search.py +104 -0
- package/assets/skills/all.md +245 -0
- package/assets/skills/android.md +168 -0
- package/assets/skills/flutter.md +153 -0
- package/assets/skills/ios.md +149 -0
- package/assets/skills/react-native.md +154 -0
- package/assets/templates/base/quick-reference.md +41 -0
- package/assets/templates/base/skill-content.md +60 -0
- package/assets/templates/platforms/agent.json +11 -0
- package/assets/templates/platforms/antigravity.json +13 -0
- package/assets/templates/platforms/claude.json +27 -0
- package/assets/templates/platforms/codebuddy.json +11 -0
- package/assets/templates/platforms/codex.json +11 -0
- package/assets/templates/platforms/continue.json +11 -0
- package/assets/templates/platforms/copilot.json +11 -0
- package/assets/templates/platforms/cursor.json +11 -0
- package/assets/templates/platforms/gemini.json +11 -0
- package/assets/templates/platforms/kiro.json +11 -0
- package/assets/templates/platforms/opencode.json +11 -0
- package/assets/templates/platforms/qoder.json +11 -0
- package/assets/templates/platforms/roocode.json +11 -0
- package/assets/templates/platforms/trae.json +11 -0
- package/assets/templates/platforms/windsurf.json +11 -0
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +94 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/update.d.ts +2 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +28 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/versions.d.ts +2 -0
- package/dist/commands/versions.d.ts.map +1 -0
- package/dist/commands/versions.js +30 -0
- package/dist/commands/versions.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +23 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +24 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +103 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
Category,Guideline,Description,Do,Dont,Code Good,Code Bad,Severity,Docs URL
|
|
2
|
+
Widgets,Prefer StatelessWidget,Use StatelessWidget when no mutable state needed,StatelessWidget for presentation-only widgets,StatefulWidget for everything,"class Greeting extends StatelessWidget { const Greeting(this.name); }","class Greeting extends StatefulWidget // no state needed",Medium,https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html
|
|
3
|
+
Widgets,Use const Constructors,Use const constructors for compile-time optimization,const for widgets with compile-time known values,Non-const for static content,"const Text('Hello World')","Text('Hello World') // not const",High,https://dart.dev/guides/language/language-tour#constant-constructors
|
|
4
|
+
Widgets,Keep Build Methods Pure,Build method should be pure no side effects,Only describe UI in build method,Trigger network calls or setState in build,"Widget build(ctx) { return Text(widget.title); }","Widget build(ctx) { fetchData(); return Text(''); }",Critical,
|
|
5
|
+
Widgets,Extract Widgets not Methods,Extract separate widget classes not helper methods,New widget class for reusable UI pieces,Private methods returning Widget,"class ItemCard extends StatelessWidget {}","Widget _buildCard() { return Card(); } // no optimization boundary",Medium,
|
|
6
|
+
Widgets,Use Keys Correctly,Provide keys when widget identity matters,Key for items in lists preserving state,Keys on every widget or none on list items,"ListView.builder(itemBuilder: (ctx i) => Item(key: ValueKey(items[i].id)))","ListView.builder(itemBuilder: (ctx i) => Item()) // no key",High,https://api.flutter.dev/flutter/foundation/Key-class.html
|
|
7
|
+
Widgets,Dispose Controllers,Always dispose controllers and listeners,Override dispose for TextEditingController ScrollController,Skip dispose causing memory leaks,"@override void dispose() { _controller.dispose(); super.dispose(); }","No dispose() override",High,
|
|
8
|
+
Widgets,Use Widget Inspector,Debug widget tree with Flutter DevTools,Use Widget Inspector for layout debugging,print statements for layout debugging,"Open DevTools > Flutter Inspector > Select Widget Mode","print('width: ${size.width}')",Low,https://docs.flutter.dev/tools/devtools/inspector
|
|
9
|
+
Widgets,Prefer Composition,Compose widgets instead of extending them,Combine existing widgets via composition,Extend RenderBox for simple layouts,"class MyCard extends StatelessWidget { Container(child: widget.child) }","class MyContainer extends Container {} // fragile",Medium,
|
|
10
|
+
State,BLoC Events Over Methods,Use events not method calls with BLoC,Add events for state changes,Call methods directly on BLoC,"bloc.add(LoadItems())","bloc.loadItems() // breaks unidirectional flow",High,https://bloclibrary.dev/
|
|
11
|
+
State,Cubit for Simple State,Use Cubit when events are overkill,Cubit for simple state without complex events,BLoC for toggling a boolean,"class CounterCubit extends Cubit<int> { void increment() => emit(state + 1); }","class CounterBloc extends Bloc<Event State> // overkill",Medium,
|
|
12
|
+
State,Immutable State,Always use immutable state objects,Use freezed or copyWith for state updates,Mutate state directly,"emit(state.copyWith(loading: false items: newItems))","state.items.add(newItem); emit(state) // mutation",Critical,
|
|
13
|
+
State,Scoped Providers,Scope state providers to feature widgets,Provide BLoC at feature route level,Global BLoC for feature-specific state,"BlocProvider(create: (_) => CartBloc() child: CartPage())","Global CartBloc at app level",Medium,
|
|
14
|
+
State,Selector for Partial Rebuild,Use BlocSelector for granular rebuilds,Select specific state fields to rebuild,BlocBuilder rebuilding on every change,"BlocSelector<MyBloc MyState String>(selector: (s) => s.title builder: ...)","BlocBuilder<MyBloc MyState>(builder: ...) // every change",High,
|
|
15
|
+
State,Repository Pattern,Abstract data sources behind Repository,Repository mediates API cache database,Direct API calls from BLoC,"class UserRepo { Future<User> getUser(int id) async { return cache[id] ?? await api.getUser(id); } }","class UserBloc { final dio = Dio(); }",High,
|
|
16
|
+
Navigation,GoRouter for Navigation,Use GoRouter for declarative routing,GoRouter with typed routes and deep links,Navigator.push for everything,"GoRouter(routes: [GoRoute(path: '/' builder: (ctx state) => Home())])","Navigator.push(context MaterialPageRoute(builder: (_) => Page()))",High,https://pub.dev/packages/go_router
|
|
17
|
+
Navigation,ShellRoute for Tabs,Use ShellRoute for persistent bottom navigation,ShellRoute wraps scaffold with nested nav,Recreate scaffold on each tab route,"ShellRoute(builder: (ctx state child) => ScaffoldWithNav(child: child))","Custom tab logic with IndexedStack manual routes",Medium,
|
|
18
|
+
Navigation,Route Guards,Implement route guards for auth protection,GoRouter redirect for authentication checks,No route protection for auth screens,"redirect: (ctx state) { if (!isLoggedIn) return '/login'; return null; }","No redirect unauthenticated users see protected",High,
|
|
19
|
+
Navigation,Typed Route Params,Use typed path parameters,Typed parameters with GoRouterState,Pass complex objects via route strings,"GoRoute(path: '/item/:id' builder: (ctx s) => ItemPage(id: int.parse(s.pathParameters['id']!)))","Navigator.pushNamed(ctx '/item' arguments: obj)",Medium,
|
|
20
|
+
Performance,Use RepaintBoundary,Isolate expensive widgets with RepaintBoundary,Wrap frequently animating widgets,Let animations trigger parent repaints,"RepaintBoundary(child: AnimatedWidget())","AnimatedWidget() in complex parent",Medium,
|
|
21
|
+
Performance,ListView.builder Always,Always use ListView.builder for lists,Builder creates items lazily on demand,ListView with children for large lists,"ListView.builder(itemCount: 1000 itemBuilder: (ctx i) => Item(items[i]))","ListView(children: items.map((i) => Item(i)).toList())",High,
|
|
22
|
+
Performance,Avoid Opacity Widget,Use color opacity instead of Opacity widget,Set opacity on color or AnimatedOpacity,Opacity widget on complex subtrees,"Container(color: Colors.black.withOpacity(0.5))","Opacity(opacity: 0.5 child: ComplexWidget())",Medium,https://docs.flutter.dev/perf/best-practices
|
|
23
|
+
Performance,compute for Heavy Work,Offload heavy computation to isolate,compute() for JSON parsing image processing,Heavy work on main isolate blocking UI,"final parsed = await compute(jsonDecode largeString)","final parsed = jsonDecode(largeString) // blocks",High,
|
|
24
|
+
Performance,Cache Network Images,Always cache network images,CachedNetworkImage with placeholder,Image.network without caching,"CachedNetworkImage(imageUrl: url placeholder: (ctx url) => Shimmer())","Image.network(url) // re-fetches every rebuild",High,
|
|
25
|
+
Performance,Profile in Release Mode,Profile performance in release mode,flutter run --release for perf testing,Profile in debug mode much slower,"flutter run --profile for accurate data","flutter run (debug) complain about jank",High,https://docs.flutter.dev/perf/best-practices
|
|
26
|
+
Performance,Minimize Widget Depth,Keep widget tree as flat as possible,Reduce nesting use proper layout widgets,20+ levels of nesting,"Row(children: [Expanded(child: Text('Hi')) Icon(Icons.star)])","Container(Padding(Center(Container(Text('Hi')))))",Medium,
|
|
27
|
+
Performance,SliverList for Mixed Scroll,Use CustomScrollView with Slivers for mixed content,Slivers for headers + lists + grids in one scroll,Multiple ListViews in SingleChildScrollView,"CustomScrollView(slivers: [SliverAppBar() SliverList() SliverGrid()])","SingleChildScrollView(Column([ListView() GridView()]))",High,
|
|
28
|
+
Testing,BLoC Test Pattern,Use blocTest for testing BLoC transitions,blocTest helper with build act expect,Manual stream testing with async gaps,"blocTest<MyBloc MyState>('loads' build: () => MyBloc(mock) act: (b) => b.add(Load()) expect: () => [Loading() Loaded()])","test(() async { bloc.add(Load()); await Future.delayed(Duration(seconds:1)); })",High,https://pub.dev/packages/bloc_test
|
|
29
|
+
Testing,Widget Test Pump,Always pump after triggering state changes,tester.pump() or pumpAndSettle() after actions,Expect changes without pumping,"await tester.tap(find.byType(Button)); await tester.pump(); expect(find.text('1') findsOneWidget);","await tester.tap(find.byType(Button)); expect(find.text('1') findsOneWidget);",Critical,
|
|
30
|
+
Testing,Mock with Mocktail,Use mocktail for mocking in tests,Simple mocking without code generation,No mocking testing with real deps,"class MockRepo extends Mock implements UserRepository {}; when(() => mock.getUser(1)).thenAnswer((_) async => User.mock)","Test with real API/database",High,https://pub.dev/packages/mocktail
|
|
31
|
+
Testing,Golden Tests,Use golden tests for visual regression,Generate and compare golden files,Only manual visual testing,"await expectLater(find.byType(MyWidget) matchesGoldenFile('my_widget.png'));","Run app and screenshot manually",Low,
|
|
32
|
+
Testing,Integration Test,Use integration_test for device testing,Test full flows on real device/emulator,Only unit and widget tests,"testWidgets('full flow' (tester) async { app.main(); await tester.pumpAndSettle(); })","No integration tests",Medium,https://docs.flutter.dev/testing/integration-tests
|
|
33
|
+
Dart,Null Safety,Leverage Dart null safety properly,Non-nullable by default add ? only when needed,Excessive use of ! operator,"final String name; // non-nullable","final String? name; name!.length // force unwrap",High,
|
|
34
|
+
Dart,Extension Methods,Use extension methods for utility functions,Extend types with domain-specific helpers,Top-level utility functions,"extension StringX on String { bool get isEmail => contains('@'); }","bool isEmail(String s) => s.contains('@');",Low,
|
|
35
|
+
Dart,Sealed Classes,Use sealed classes for exhaustive state,Sealed class for finite state variants,Multiple boolean flags,"sealed class AuthState {} class Authenticated extends AuthState {}","class AuthState { bool isLoggedIn; bool isLoading; }",High,
|
|
36
|
+
Dart 3,Pattern Matching,Use Dart 3 pattern matching for exhaustive checks,Use switch expressions with patterns for type-safe branching,Use if-else chains or old switch statements,final message = switch (state) { Loading() => 'Loading...' Success(:final data) => data Error(:final msg) => msg },if (state is Loading) return 'Loading'; else if (state is Success) ...,High,https://dart.dev/language/patterns
|
|
37
|
+
Dart 3,Records,Use Records for lightweight data grouping,Return multiple values using records instead of custom classes,Create single-use classes for grouped return values,(String name int age) getUser() => ('John' 30); final (name age) = getUser(),class UserResult { String name; int age; } UserResult getUser() => UserResult('John' 30),Medium,https://dart.dev/language/records
|
|
38
|
+
Dart 3,Sealed Classes,Use sealed classes for exhaustive state handling,Define finite state variants with sealed classes,Use enum or abstract class with manual type checking,sealed class AuthState {} class Authenticated extends AuthState { final User user; } class Unauthenticated extends AuthState {},abstract class AuthState {} // compiler doesn't enforce exhaustive switch,High,https://dart.dev/language/class-modifiers#sealed
|
|
39
|
+
Riverpod,Generated Providers,Use @riverpod annotation for code-generated providers,Annotate functions/classes with @riverpod for auto-generated providers,Manually create providers with complex generic types,@riverpod Future<List<Todo>> todos(Ref ref) async => ref.read(apiProvider).fetchTodos(),final todosProvider = FutureProvider<List<Todo>>((ref) async => ref.read(apiProvider).fetchTodos()),Medium,https://riverpod.dev/docs/concepts/about_code_generation
|
|
40
|
+
Riverpod,AutoDispose,Use autoDispose for providers that should clean up,Let code gen handle autoDispose; use keepAlive() for persistent,Leak provider state after screen disposed,@riverpod Future<User> user(Ref ref) async { final api = ref.read(apiProvider); return api.getUser(); } // auto-disposed,final userProvider = FutureProvider((ref) => ref.read(apiProvider).getUser()); // never disposed,High,https://riverpod.dev/docs/concepts/modifiers/auto_dispose
|
|
41
|
+
Navigation,go_router Setup,Configure go_router with proper redirect and error handling,Use GoRouter with redirect guards and error builder,Use Navigator.push everywhere without routing structure,GoRouter(routes: [GoRoute(path: '/' builder: (ctx state) => HomeScreen()) GoRoute(path: '/detail/:id' builder: (ctx state) => DetailScreen(id: state.pathParameters['id']!))]; redirect: authGuard),Navigator.of(context).push(MaterialPageRoute(builder: (_) => DetailScreen())) // no deep linking,High,https://pub.dev/packages/go_router
|
|
42
|
+
Navigation,ShellRoute,Use ShellRoute for persistent navigation bars,Wrap tab destinations in ShellRoute for persistent scaffold,Recreate bottom nav on every route,ShellRoute(builder: (ctx state child) => ScaffoldWithNav(child: child) routes: [GoRoute(path: '/home' builder: ...) GoRoute(path: '/profile' builder: ...)]),// Separate MaterialApp push for each tab; navigation bar rebuilds,Medium,https://pub.dev/packages/go_router
|
|
43
|
+
State,freezed Models,Use freezed for immutable state and union types,Generate immutable classes with copyWith and equality,Write boilerplate equals hashCode copyWith manually,@freezed class TodoState with _$TodoState { factory TodoState({required List<Todo> items @Default(false) bool loading}) = _TodoState; },class TodoState { List<Todo> items; bool loading; TodoState({required this.items this.loading = false}); } // mutable,High,https://pub.dev/packages/freezed
|
|
44
|
+
DI,Injectable Setup,Use injectable with get_it for code-generated DI,Annotate classes with @injectable @singleton @lazySingleton,Register everything manually in get_it,@injectable class UserRepository { final ApiClient _api; UserRepository(this._api); },GetIt.instance.registerFactory(() => UserRepository(GetIt.instance<ApiClient>())); // manual,Medium,https://pub.dev/packages/injectable
|
|
45
|
+
UI,Material 3 Theming,Use Material 3 with ColorScheme.fromSeed,Generate theme from seed color for M3 compliance,Hardcode individual colors throughout the app,ThemeData(useMaterial3: true colorSchemeSeed: Colors.deepPurple),ThemeData(primaryColor: Colors.blue accentColor: Colors.red) // M2; deprecated,Medium,https://docs.flutter.dev/ui/design/material
|
|
46
|
+
UI,Sliver Patterns,Use slivers for complex scrollable layouts,Combine SliverAppBar SliverList SliverGrid in CustomScrollView,Nest ListView inside Column inside SingleChildScrollView,CustomScrollView(slivers: [SliverAppBar(floating: true) SliverList(delegate: SliverChildBuilderDelegate(...))]),SingleChildScrollView(child: Column(children: [Container(height: 200) ListView(shrinkWrap: true physics: NeverScrollableScrollPhysics())])) // horrible,High,https://api.flutter.dev/flutter/widgets/CustomScrollView-class.html
|
|
47
|
+
Testing,Widget Test with Providers,Test widgets that depend on Riverpod providers,Use ProviderScope with overrides for widget tests,Test with real API calls or skip widget tests,testWidgets('shows data' (tester) async { await tester.pumpWidget(ProviderScope(overrides: [dataProvider.overrideWith((_) => mockData)] child: MaterialApp(home: MyScreen()))) }),// No widget tests; only manual testing,High,https://riverpod.dev/docs/essentials/testing
|
|
48
|
+
Performance,Build Method Optimization,Keep build methods fast and pure,Extract complex widgets; avoid computation in build,Put API calls computation or side effects in build method,Widget build(context) => Column(children: [const Header() ItemList(items: items)]); // const + extracted,Widget build(context) { final data = jsonDecode(heavyJson); return Column(...); } // computation in build,High,https://docs.flutter.dev/perf/best-practices
|
|
49
|
+
Platform,Platform-Specific UI,Adapt UI for iOS and Android conventions,Use Platform checks or .adaptive constructors,Use Material design on iOS where it looks wrong,Switch.adaptive(value: v onChanged: onChanged); // native look per platform,Switch(value: v onChanged: onChanged); // Material switch on iOS,Medium,https://docs.flutter.dev/platform-integration/platform-adaptations
|
|
50
|
+
Accessibility,Semantics Widget,Use Semantics widget for accessibility,Wrap custom widgets with Semantics for screen reader support,Skip semantics on interactive custom widgets,Semantics(label: 'Play video' button: true child: CustomPlayButton()),GestureDetector(onTap: play child: Icon(Icons.play)) // no accessibility label,High,https://api.flutter.dev/flutter/widgets/Semantics-class.html
|
|
51
|
+
Architecture,Repository Pattern,Implement repository pattern for data layer,Abstract data sources behind repository interface,Call API directly from provider or widget,abstract class TodoRepo { Future<List<Todo>> getAll(); } class TodoRepoImpl implements TodoRepo { final ApiClient _api; Future<List<Todo>> getAll() => _api.fetchTodos(); },final todos = await Dio().get('/todos'); // API call in widget,High,
|
|
52
|
+
Error Handling,Result Type,Use Result type or Either for error handling,Return typed results instead of throwing exceptions,Catch Exception everywhere or let crashes propagate,sealed class Result<T> { factory Result.success(T data) = Success; factory Result.failure(String msg) = Failure; },try { return await api.fetch(); } catch (e) { print(e); return null; } // swallowed error,Medium,
|
|
53
|
+
Dart 3,Extension Types,Use extension types for zero-cost type wrappers,Create type-safe wrappers without runtime overhead,Use typedef or raw types for IDs and values,extension type UserId(String value) implements String {} void fetchUser(UserId id) { ... },typedef UserId = String; // no type safety; can pass any string,Medium,https://dart.dev/language/extension-types
|
|
54
|
+
Internationalization,Flutter Intl,Use flutter_localizations for proper i18n,Generate localization files from ARB,Hardcode strings in widgets,Text(AppLocalizations.of(context)!.helloWorld),Text('Hello World') // not localized,Medium,https://docs.flutter.dev/ui/accessibility-and-internationalization/internationalization
|
|
55
|
+
State,AsyncNotifier,Use AsyncNotifier for async state in Riverpod,Build async state with AsyncNotifier or AsyncNotifierProvider,Use FutureProvider and manually rebuild,@riverpod class TodoList extends _$TodoList { @override Future<List<Todo>> build() => ref.read(apiProvider).fetchTodos(); Future<void> add(Todo todo) async { state = const AsyncLoading(); state = AsyncData(await ref.read(apiProvider).addTodo(todo)); } },// Manual state management with FutureProvider + StateProvider,High,https://riverpod.dev/docs/providers/async_notifier_provider
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
Category,Guideline,Description,Do,Dont,Code Good,Code Bad,Severity,Docs URL
|
|
2
|
+
SwiftUI,Use @State for Local State,Own view-local state with @State,@State for simple value types owned by view,@State for shared or complex state,"@State private var isExpanded = false","@State var viewModel = ViewModel() // wrong",High,https://developer.apple.com/documentation/swiftui/state
|
|
3
|
+
SwiftUI,Use @StateObject for ViewModels,Initialize ObservableObject with @StateObject,@StateObject in parent @ObservedObject in children,@ObservedObject for creation recreates on redraw,"@StateObject private var vm = MyViewModel()","@ObservedObject var vm = MyViewModel() // recreated",Critical,https://developer.apple.com/documentation/swiftui/stateobject
|
|
4
|
+
SwiftUI,Use @Environment,Access shared data via environment,@Environment for system @EnvironmentObject for custom,Pass dependencies through all init parameters,"@Environment(\.colorScheme) var colorScheme","init(colorScheme: ColorScheme) // drilling",Medium,https://developer.apple.com/documentation/swiftui/environment
|
|
5
|
+
SwiftUI,Prefer Value Types,Use structs over classes for models,Struct for data models enum for state,Classes for everything,"struct User { let name: String; let email: String }","class User { var name: String; var email: String }",Medium,
|
|
6
|
+
SwiftUI,Extract Subviews,Break complex views into smaller subviews,Extract when view body exceeds 30 lines,Massive view body hundreds of lines,"VStack { HeaderView(); ContentView(); FooterView() }","var body: some View { /* 200 lines */ }",Medium,
|
|
7
|
+
SwiftUI,Use ViewModifier,Create reusable ViewModifiers for common styling,ViewModifier for repeated style combinations,Duplicating modifier chains,"struct CardStyle: ViewModifier { func body(content: Content) -> some View { content.padding().background(.white).cornerRadius(12) } }",".padding().background(.white).cornerRadius(12) repeated",Low,
|
|
8
|
+
SwiftUI,Task over onAppear,Use .task instead of .onAppear for async work,.task handles cancellation automatically,.onAppear with manual Task management,".task { await vm.loadData() }",".onAppear { Task { await vm.loadData() } }",Medium,https://developer.apple.com/documentation/swiftui/view/task(priority:_:)
|
|
9
|
+
SwiftUI,NavigationStack,Use NavigationStack over NavigationView,NavigationStack with value-based navigation,NavigationView with NavigationLink destination,"NavigationStack(path: $path) { .navigationDestination(for: Item.self) { DetailView($0) } }","NavigationView { NavigationLink(destination: DetailView()) {} }",High,https://developer.apple.com/documentation/swiftui/navigationstack
|
|
10
|
+
SwiftUI,Lazy Stacks,Use LazyVStack/LazyHStack for long lists,LazyVStack inside ScrollView for large data,VStack for hundreds of items,"ScrollView { LazyVStack { ForEach(items) { ItemView($0) } } }","ScrollView { VStack { ForEach(items) { ItemView($0) } } }",High,
|
|
11
|
+
SwiftUI,Equatable Conformance,Conform models to Equatable for efficient diffing,Equatable on data models for efficient updates,No Equatable causing unnecessary redraws,"struct Item: Identifiable Equatable { let id: UUID; let title: String }","struct Item: Identifiable { let id: UUID; let title: String }",Medium,
|
|
12
|
+
Combine,async/await over Combine,Prefer async/await for new simple async code,async/await for one-shot async operations,Combine for simple one-shot async,"func fetchUser() async throws -> User { try await api.getUser() }","func fetchUser() -> AnyPublisher<User Never> { }",Medium,
|
|
13
|
+
Combine,Cancel Subscriptions,Store and cancel Combine subscriptions,Store in Set<AnyCancellable> cancel on deinit,Let subscriptions leak,"var cancellables = Set<AnyCancellable>(); pub.sink {}.store(in: &cancellables)","pub.sink { self.handle($0) } // not stored",High,
|
|
14
|
+
Combine,Receive on Main,Receive Combine values on main thread,Use .receive(on: DispatchQueue.main) before sink,Update UI from background thread,"pub.receive(on: DispatchQueue.main).sink { self.items = $0 }","pub.sink { self.items = $0 } // may be background",High,
|
|
15
|
+
Combine,Error Handling,Handle Combine publisher errors properly,Use catch replaceError or mapError,Ignore errors with assertNoFailure,"pub.catch { _ in Just(fallback) }.sink {}","pub.assertNoFailure().sink {} // crashes on error",High,
|
|
16
|
+
Combine,Debounce Input,Debounce user input before API calls,Debounce search text 300ms before searching,API call on every keystroke,"$searchText.debounce(for: .milliseconds(300) scheduler: RunLoop.main)","$searchText.sink { api.search($0) }",Medium,
|
|
17
|
+
Architecture,Coordinator Pattern,Use Coordinators for navigation logic,Separate navigation from views and VMs,Navigation logic in views,"class AppCoordinator { func showDetail(item: Item) { path.append(item) } }","Button { NavigationLink(destination: DetailView()) }",Medium,
|
|
18
|
+
Architecture,Protocol-Oriented,Use protocols for abstraction and testability,Define protocols for services and repositories,Concrete types everywhere,"protocol UserRepository { func getUser(id: Int) async throws -> User }","class UserService { func getUser() } // no protocol",High,
|
|
19
|
+
Architecture,Dependency Container,Use dependency container for DI,@EnvironmentObject or Factory for DI,Manual initialization everywhere,"@EnvironmentObject var userService: UserService","let service = UserService() // inline",Medium,
|
|
20
|
+
Architecture,Error Handling Strategy,Define consistent error handling,Typed errors with associated values,String error messages everywhere,"enum AppError: Error { case network(URLError); case validation(String) }","throw NSError(domain: '' code: -1)",Medium,
|
|
21
|
+
Architecture,Modular Architecture,Separate into Swift Packages,Use SPM for feature and core modules,Everything in single target,"Package: CoreNetwork FeatureHome FeatureProfile","Single Xcode target with all code",Medium,
|
|
22
|
+
Architecture,Observable Macro,Use @Observable macro iOS 17+ over ObservableObject,@Observable for simpler observation,ObservableObject with @Published for new projects,"@Observable class UserViewModel { var user: User? }","class UserViewModel: ObservableObject { @Published var user: User? }",Medium,https://developer.apple.com/documentation/observation/observable()
|
|
23
|
+
Architecture,Actor Thread Safety,Use Swift actors for thread-safe state,Actor for shared mutable state,DispatchQueue.sync for thread safety,"actor UserCache { private var users: [Int: User] = [:] }","class UserCache { let queue = DispatchQueue(label: 'cache') }",High,
|
|
24
|
+
Architecture,Sendable Conformance,Mark types Sendable for concurrency safety,Sendable for types crossing concurrency boundaries,Ignoring Sendable warnings,"struct UserDTO: Sendable { let name: String }","class UserDTO { var name: String } // not Sendable",Medium,https://developer.apple.com/documentation/swift/sendable
|
|
25
|
+
Performance,Instruments Profiling,Profile with Instruments regularly,Time Profiler Allocations Leaks,Only test on Simulator with print,"Product > Profile > Time Profiler","print(Date()) for timing",High,
|
|
26
|
+
Performance,Image Caching,Cache images with Kingfisher/Nuke,Use Kingfisher with downsampling for lists,Load images without cache,"KFImage(url).downsampling(size: CGSize(width: 200 height: 200))","AsyncImage(url: url) // no caching",High,
|
|
27
|
+
Performance,Background Fetch,Use BGTaskScheduler for background work,Schedule BGAppRefreshTask for periodic updates,Timer-based background polling,"BGTaskScheduler.shared.register(forTaskWithIdentifier: 'refresh') {}","Timer.scheduledTimer(interval: 60) {} // killed",High,https://developer.apple.com/documentation/backgroundtasks
|
|
28
|
+
Performance,Core Data Performance,Optimize Core Data fetch requests,NSFetchedResultsController batch size predicates,Fetch all records without batching,"request.fetchBatchSize = 20; request.predicate = active == YES","context.fetch(NSFetchRequest(entityName: 'Entity'))",Medium,
|
|
29
|
+
Performance,View Identity,Use stable identity for SwiftUI views,Stable id prevents unnecessary recreation,Random or changing id values,"ForEach(items id: \.stableId) { ItemView(item: $0) }","ForEach(items id: \.self) { } // mutable models",Medium,
|
|
30
|
+
Performance,Reduce View Updates,Minimize view body evaluation,Use EquatableView and targeted state changes,Broad state changes triggering full redraws,"EquatableView(content: ExpensiveView(data: data))","@State var flag // triggers full body evaluation",Medium,
|
|
31
|
+
Performance,Main Actor,Use @MainActor for UI-related code,Mark ViewModels and UI code with @MainActor,Manual DispatchQueue.main.async,"@MainActor class MyViewModel { func updateUI() {} }","DispatchQueue.main.async { self.updateUI() }",High,https://developer.apple.com/documentation/swift/mainactor
|
|
32
|
+
Testing,XCTest Async,Use async test methods for async code,async test functions with await,XCTestExpectation for async testing,"func testFetch() async throws { let user = try await vm.fetchUser(); XCTAssertEqual(user.name 'John') }","func testFetch() { let exp = expectation(); wait(for: [exp]) }",Medium,
|
|
33
|
+
Testing,Mock with Protocol,Mock dependencies via protocol conformance,Create mock implementing protocol for tests,Test with real services,"class MockUserRepo: UserRepository { func getUser(id: Int) async -> User { .mock } }","Test using real API calls",High,
|
|
34
|
+
Testing,Snapshot Testing,Use swift-snapshot-testing for visual regression,Snapshot test key UI states,Manual visual verification,"assertSnapshot(matching: MyView() as: .image(layout: .device(.iPhone13)))","Run app and visually check",Low,https://github.com/pointfreeco/swift-snapshot-testing
|
|
35
|
+
Testing,Test ViewModels,Test ViewModel logic independently,Test state changes outputs and side effects,Test views directly,"func testLoad() async { await vm.load(); XCTAssertEqual(vm.items.count 10) }","Test by rendering SwiftUI view",High,
|
|
36
|
+
Testing,XCUITest E2E,Use XCUITest for end-to-end flows,Test critical journeys with accessibility IDs,No automated UI testing,"let app = XCUIApplication(); app.launch(); app.buttons['Login'].tap()","Manual testing before release",Medium,https://developer.apple.com/documentation/xctest/xcuiapplication
|
|
37
|
+
SwiftData,@Model Macro,Use @Model for persistence instead of CoreData entities,Annotate model classes with @Model for automatic persistence,Use NSManagedObject subclasses for new projects,@Model class Todo { var title: String; var isDone: Bool; init(title: String) { self.title = title; isDone = false } },class Todo: NSManagedObject { @NSManaged var title: String } // CoreData boilerplate,High,https://developer.apple.com/documentation/swiftdata/model()
|
|
38
|
+
SwiftData,ModelContainer Setup,Configure SwiftData container with schema and configuration,Create ModelContainer in App with explicit schema,Initialize container in every view,@main struct App { var body: some Scene { WindowGroup { ContentView() }.modelContainer(for: [Todo.self]) } },// Create container in each ViewController separately,Medium,https://developer.apple.com/documentation/swiftdata/modelcontainer
|
|
39
|
+
SwiftData,@Query Property Wrapper,Use @Query for reactive data fetching in SwiftUI,Use @Query with sort and filter predicates,Manually fetch and manage arrays of objects,@Query(sort: \Todo.createdAt order: .reverse) var todos: [Todo],@State var todos: [Todo] = []; func loadTodos() { todos = context.fetch() },High,https://developer.apple.com/documentation/swiftdata/query
|
|
40
|
+
Swift 6,Strict Concurrency,Enable Swift 6 strict concurrency checking,Mark types with @Sendable; use actors for shared state,Ignore concurrency warnings; use shared mutable state,actor UserManager { private var users: [User] = []; func add(_ user: User) { users.append(user) } },class UserManager { var users: [User] = [] } // data race potential,Critical,https://developer.apple.com/documentation/swift/sendable
|
|
41
|
+
Swift 6,@Observable Macro,Use @Observable instead of ObservableObject for iOS 17+,Use @Observable for granular observation tracking,Use ObservableObject with multiple @Published properties,@Observable class ViewModel { var name = ''; var age = 0 },class ViewModel: ObservableObject { @Published var name = ''; @Published var age = 0 },High,https://developer.apple.com/documentation/observation/observable()
|
|
42
|
+
Swift 6,Typed Throws,Use typed throws for explicit error handling,Specify error types in function signatures,Throw and catch untyped errors,func load() throws(NetworkError) { throw .timeout },func load() throws { throw NSError(domain: '' code: 0) },Medium,https://developer.apple.com/documentation/swift
|
|
43
|
+
TipKit,App Tips,Use TipKit for contextual user guidance,Show tips for discoverable features; respect frequency rules,Show alerts or custom tooltips for feature education,struct FavoriteTip: Tip { var title: Text { Text('Add Favorites') }; var message: Text? { Text('Tap heart to save') } },UIAlertController for feature hints // modal and interruptive,Medium,https://developer.apple.com/documentation/tipkit
|
|
44
|
+
WidgetKit,Widget Timeline,Create widgets with proper timeline management,Use TimelineProvider with appropriate refresh policy,Refresh widget too frequently or not enough,func getTimeline(in context: Context completion: @escaping (Timeline<Entry>) -> ()) { let entries = [Entry(date: .now)]; completion(Timeline(entries: entries policy: .atEnd)) },Timer.scheduledTimer { WidgetCenter.shared.reloadAllTimelines() } // too frequent,High,https://developer.apple.com/documentation/widgetkit
|
|
45
|
+
App Intents,App Shortcuts,Use App Intents for Siri and Shortcuts integration,Create AppIntent structs for actionable features,Use SiriKit intents for new shortcuts,struct OrderCoffee: AppIntent { static var title: LocalizedStringResource = 'Order Coffee'; func perform() async throws -> some IntentResult { .result() } },class OrderCoffeeHandler: INExtension // old SiriKit,Medium,https://developer.apple.com/documentation/appintents
|
|
46
|
+
Live Activities,Dynamic Island,Use Live Activities and Dynamic Island for real-time updates,Show ongoing activity state in Lock Screen and Dynamic Island,Use push notifications for real-time status,struct DeliveryActivity: Widget { var body: some WidgetConfiguration { ActivityConfiguration(for: DeliveryAttributes.self) { context in DeliveryView(state: context.state) } } },Send push notification every minute for delivery status,High,https://developer.apple.com/documentation/activitykit
|
|
47
|
+
Concurrency,AsyncSequence,Use AsyncSequence for asynchronous iteration,Use for-await-in for streaming data,Use completion handler chains for sequential async,for await notification in NotificationCenter.default.notifications(named: .didUpdate) { process(notification) },NotificationCenter.addObserver { result in completion(result) } // callback hell,Medium,https://developer.apple.com/documentation/swift/asyncsequence
|
|
48
|
+
Concurrency,TaskGroup Parallelism,Use TaskGroup for structured parallel work,Process independent tasks concurrently with TaskGroup,Await tasks sequentially when they could run in parallel,let results = await withTaskGroup(of: Data.self returning: [Data].self) { group in urls.forEach { url in group.addTask { await fetch(url) } }; return await group.reduce(into: []) { $0.append($1) } },var results: [Data] = []; for url in urls { results.append(await fetch(url)) } // sequential,High,https://developer.apple.com/documentation/swift/taskgroup
|
|
49
|
+
Privacy,Privacy Manifest,Declare API reasons in privacy manifest,Add PrivacyInfo.xcprivacy with required API declarations,Ship without privacy manifest; App Store rejection,// PrivacyInfo.xcprivacy: NSPrivacyAccessedAPITypes with NSPrivacyAccessedAPITypeReasons,// No privacy manifest; rejected by App Store review,Critical,https://developer.apple.com/documentation/bundleresources/privacy_manifest_files
|
|
50
|
+
Privacy,Tracking Transparency,Request tracking permission before IDFA access,Use ATTrackingManager.requestTrackingAuthorization before tracking,Access IDFA without permission; App Store rejection,ATTrackingManager.requestTrackingAuthorization { status in if status == .authorized { enableTracking() } },let idfa = ASIdentifierManager.shared().advertisingIdentifier // without permission,Critical,https://developer.apple.com/documentation/apptrackingtransparency
|
|
51
|
+
Architecture,Navigation Path,Use NavigationPath for type-safe programmatic navigation,Maintain NavigationPath in coordinator or router,Use NavigationLink with destination for all navigation,@State private var path = NavigationPath(); NavigationStack(path: $path) { ... }; path.append(DetailRoute(id: 1)),NavigationLink(destination: DetailView(id: 1)) { Text('Go') } // scattered navigation,High,https://developer.apple.com/documentation/swiftui/navigationpath
|
|
52
|
+
Architecture,Environment Values,Use @Environment for dependency injection in SwiftUI,Pass dependencies through SwiftUI Environment,Create singletons or pass dependencies through init chains,@Environment(\.modelContext) private var context; @Environment(\.dismiss) private var dismiss,static let shared = DatabaseManager() // singleton anti-pattern,Medium,https://developer.apple.com/documentation/swiftui/environment
|
|
53
|
+
Accessibility,Dynamic Type,Support Dynamic Type for text scaling,Use system fonts and dynamic type sizes,Hardcode font sizes; ignore accessibility settings,Text('Hello').font(.body) // scales with Dynamic Type,Text('Hello').font(.system(size: 16)) // fixed size; ignores user preference,High,https://developer.apple.com/documentation/swiftui/dynamictypesize
|
|
54
|
+
Accessibility,VoiceOver Labels,Add accessibility labels to all interactive elements,Use accessibilityLabel and accessibilityHint,Leave images and buttons without labels,Image(systemName: 'heart.fill').accessibilityLabel('Add to favorites'),Image(systemName: 'heart.fill') // VoiceOver says 'heart.fill image',High,https://developer.apple.com/documentation/accessibility
|
|
55
|
+
Performance,Lazy Navigation,Use lazy loading for navigation destinations,Use NavigationLink with lazy value-based navigation,Load all destination views eagerly,NavigationLink(value: item) { ItemRow(item) } // destination loaded on tap,NavigationLink(destination: HeavyView()) { Text('Go') } // HeavyView created immediately,Medium,https://developer.apple.com/documentation/swiftui/navigationlink
|
|
56
|
+
Performance,View Identity,Use stable IDs for List and ForEach performance,Use Identifiable protocol with stable IDs,Use array index or random UUID as identifier,ForEach(items) { item in ItemRow(item: item) } // items: Identifiable,ForEach(0..<items.count id: \.self) { i in ItemRow(item: items[i]) } // index-based,High,
|
|
57
|
+
UI,SF Symbols,Use SF Symbols for consistent iconography,Use system SF Symbols with rendering modes,Use custom PNG icons for common system actions,Image(systemName: 'star.fill').symbolRenderingMode(.hierarchical),UIImage(named: 'custom_star_icon') // custom asset for standard action,Low,https://developer.apple.com/sf-symbols/
|
|
58
|
+
UI,ViewModifier,Create custom ViewModifiers for reusable styling,Extract repeated styling into ViewModifier,Duplicate modifier chains across views,struct CardStyle: ViewModifier { func body(content: Content) -> some View { content.padding().background(.regularMaterial).cornerRadius(12) } },Text('A').padding().background(.regularMaterial).cornerRadius(12) // duplicated everywhere,Medium,https://developer.apple.com/documentation/swiftui/viewmodifier
|
|
59
|
+
Testing,Preview Macros,Use #Preview macro for SwiftUI previews,Use #Preview with different states and configurations,No previews or outdated preview code,#Preview('Dark Mode') { ContentView().preferredColorScheme(.dark) },struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } // old API,Low,https://developer.apple.com/documentation/swiftui/preview()
|
|
60
|
+
Architecture,Transferable Protocol,Use Transferable for drag-and-drop and sharing,Implement Transferable for data sharing between apps,Use UIActivityItemProvider manually,struct Photo: Transferable { static var transferRepresentation: some TransferRepresentation { FileRepresentation(contentType: .png) { ... } } },// Manual UIActivityViewController setup with custom item provider,Medium,https://developer.apple.com/documentation/coretransferable/transferable
|
|
61
|
+
Concurrency,Actor Isolation,Use actor isolation for thread-safe shared state,Isolate shared mutable state in actors; use MainActor for UI,Use DispatchQueue.sync for thread safety,@MainActor class ViewModel { var items: [Item] = [] },DispatchQueue.main.async { self.items = newItems } // old pattern,High,https://developer.apple.com/documentation/swift/actor
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
Category,Guideline,Description,Do,Dont,Code Good,Code Bad,Severity,Docs URL
|
|
2
|
+
Components,Functional Components,Always use functional components with hooks,Functional component with hooks for all new code,Class components for new code,"const MyScreen = () => { const [data setData] = useState(null); return <View />; }","class MyScreen extends React.Component { render() { return <View /> } }",High,https://react.dev/reference/react/hooks
|
|
3
|
+
Components,React.memo,Wrap expensive components with React.memo,Memo for components that re-render with same props,Memo on every component or none,"const ExpensiveList = React.memo(({ items }) => <FlatList data={items} />)","const ExpensiveList = ({ items }) => <FlatList data={items} />",High,
|
|
4
|
+
Components,useMemo and useCallback,Memoize expensive computations and callbacks,useMemo for derived data useCallback for handlers,Wrap everything in useMemo/useCallback,"const filtered = useMemo(() => items.filter(i => i.active) [items])","const filtered = items.filter(i => i.active) // every render",Medium,
|
|
5
|
+
Components,Custom Hooks,Extract reusable logic into custom hooks,Custom hook for shared stateful logic,Duplicate logic across components,"function useUser(id) { const [user setUser] = useState(null); useEffect(() => { fetch(id).then(setUser) } [id]); return user; }","Copy-paste fetch logic everywhere",Medium,https://react.dev/learn/reusing-logic-with-custom-hooks
|
|
6
|
+
Components,Avoid Inline Styles,Define styles outside with StyleSheet,StyleSheet.create for optimized styles,Inline style objects causing re-renders,"const styles = StyleSheet.create({ container: { flex: 1 padding: 16 } })","<View style={{ flex: 1 padding: 16 }} /> // new obj every render",Medium,
|
|
7
|
+
Components,Error Boundaries,Implement error boundaries for crash resilience,Error boundary wrapping feature sections,No error boundaries crashes whole app,"<ErrorBoundary fallback={<ErrorScreen />}><HomeScreen /></ErrorBoundary>","No error handling crashes propagate to root",High,
|
|
8
|
+
Components,Platform-Specific Code,Use Platform module for differences,Platform.select or .ios.js/.android.js files,Scattered platform checks everywhere,"Platform.select({ ios: { shadow } android: { elevation: 4 } })","if (Platform.OS === 'ios') {} else {} scattered",Medium,https://reactnative.dev/docs/platform-specific-code
|
|
9
|
+
Components,TypeScript,Use TypeScript for type safety,Strict TypeScript with proper component typing,JavaScript without types,"const MyComponent: React.FC<Props> = ({ title onPress }) => {}","function MyComponent(props) {} // no types",High,
|
|
10
|
+
State,useState for Local State,Keep local state local with useState,useState for component-scoped UI state,Global store for local modal visibility,"const [isOpen setIsOpen] = useState(false)","dispatch(toggleModal()) // Redux for modal",Medium,
|
|
11
|
+
State,useReducer for Complex,Use useReducer when state logic is complex,useReducer for multiple related transitions,Multiple useState for related values,"const [state dispatch] = useReducer(reducer initialState)","const [loading setLoading] = useState(); const [error setError] = useState(); const [data setData] = useState();",Medium,https://react.dev/reference/react/useReducer
|
|
12
|
+
State,React Query for Server,Use React Query for API data and caching,React Query for server state Redux for client,Redux for everything including API cache,"const { data isLoading } = useQuery({ queryKey: ['users'] queryFn: fetchUsers })","useEffect(() => { setLoading(true); fetchUsers().then(setData) } [])",High,https://tanstack.com/query/latest
|
|
13
|
+
State,Zustand for Global,Use Zustand for simple global state,Zustand store for shared client state,Redux for simple counter state,"const useStore = create((set) => ({ count: 0 inc: () => set(s => ({ count: s.count+1 })) }))","createStore(combineReducers({ count: countReducer })) // overkill",Medium,https://zustand-demo.pmnd.rs/
|
|
14
|
+
State,MMKV over AsyncStorage,Use react-native-mmkv for fast storage,MMKV for synchronous fast key-value,AsyncStorage for frequent read/write,"const storage = new MMKV(); storage.set('user.name' 'John')","await AsyncStorage.setItem('user.name' 'John') // slow",Medium,
|
|
15
|
+
Navigation,React Navigation Setup,Use React Navigation with proper typing,Type-safe navigation with RootStackParamList,Untyped navigation with string routes,"type RootStack = { Home: undefined; Detail: { id: number } }; useNavigation<NativeStackNavigationProp<RootStack>>()","navigation.navigate('Detail' { id: '123' }) // untyped",High,https://reactnavigation.org/docs/typescript
|
|
16
|
+
Navigation,Deep Linking,Configure deep linking from the start,Linking config in NavigationContainer,Add deep linking as afterthought,"<NavigationContainer linking={{ prefixes: ['myapp://'] config: { screens: { Home: 'home' } } }}>","No linking configuration",Medium,https://reactnavigation.org/docs/deep-linking
|
|
17
|
+
Navigation,Screen Options,Define screen options properly,Static screenOptions on Screen component,Dynamic options causing re-renders,"<Stack.Screen name='Home' options={{ title: 'Home' headerShown: true }} />","options={() => ({ title: computeTitle() })} // recalculates",Low,
|
|
18
|
+
Navigation,Nav State Persistence,Persist navigation state for dev,Save and restore nav state in development,Lose navigation state on every reload,"<NavigationContainer onStateChange={saveState} initialState={savedState}>","No state persistence",Low,https://reactnavigation.org/docs/state-persistence
|
|
19
|
+
Performance,FlatList over ScrollView,Use FlatList for long lists never ScrollView,FlatList with keyExtractor and optimization,ScrollView with map for rendering lists,"<FlatList data={items} keyExtractor={i => i.id} renderItem={renderItem} />","<ScrollView>{items.map(i => <Item key={i.id} />)}</ScrollView>",Critical,https://reactnative.dev/docs/flatlist
|
|
20
|
+
Performance,FlashList,Use FlashList for better list performance,FlashList as drop-in FlatList replacement,FlatList for very long complex lists,"<FlashList data={items} renderItem={renderItem} estimatedItemSize={100} />","<FlatList /> for 1000+ complex items",High,https://shopify.github.io/flash-list/
|
|
21
|
+
Performance,Hermes Engine,Enable Hermes for better performance,Hermes for faster startup and lower memory,JSC engine,"hermesEnabled: true in android/app/build.gradle","hermesEnabled: false",High,https://reactnative.dev/docs/hermes
|
|
22
|
+
Performance,Extract Handlers,Extract handlers to avoid re-renders,Named functions or useCallback for handlers,Inline arrow functions in render,"const handlePress = useCallback(() => { onPress(item.id) } [item.id onPress])","<Button onPress={() => onPress(item.id)} /> // new fn every render",Medium,
|
|
23
|
+
Performance,Image Optimization,Use FastImage for optimized loading,react-native-fast-image with priority and caching,Image without caching strategy,"<FastImage source={{ uri priority: FastImage.priority.normal }} resizeMode='cover' />","<Image source={{ uri }} /> // no caching",High,
|
|
24
|
+
Performance,Reduce Bridge Traffic,Minimize native bridge communication,Batch updates use Reanimated for animations,Frequent small bridge calls in animations,"useAnimatedStyle(() => ({ transform: [{ translateY: offset.value }] }))","Animated.timing(value { toValue: 1 }).start() // bridge per frame",High,
|
|
25
|
+
Performance,Bundle Optimization,Optimize JavaScript bundle size,Tree-shake imports use dynamic import,Import entire libraries,"import { debounce } from 'lodash/debounce'","import _ from 'lodash' // 70KB+",Medium,
|
|
26
|
+
Performance,useNativeDriver,Use native driver for Animated API,nativeDriver: true for transform and opacity,nativeDriver for layout properties,"Animated.timing(value { toValue: 1 useNativeDriver: true })","Animated.timing(value { toValue: 1 useNativeDriver: false })",High,https://reactnative.dev/docs/animations#using-the-native-driver
|
|
27
|
+
Performance,Reanimated,Use react-native-reanimated for complex animations,Reanimated for gesture and layout animations,Animated API for complex interactions,"const style = useAnimatedStyle(() => ({ opacity: withTiming(visible ? 1 : 0) }))","const opacity = useRef(new Animated.Value(0)).current",High,https://docs.swmansion.com/react-native-reanimated/
|
|
28
|
+
Performance,InteractionManager,Defer expensive work after interactions,runAfterInteractions for non-urgent work,Heavy computation during navigation,"InteractionManager.runAfterInteractions(() => { processLargeDataset() })","processLargeDataset() // blocks animation",Medium,https://reactnative.dev/docs/interactionmanager
|
|
29
|
+
Testing,Testing Library,Use @testing-library/react-native,Test user behavior not implementation,Enzyme or shallow rendering,"const { getByText } = render(<MyComponent />); fireEvent.press(getByText('Submit'))","shallow(<MyComponent />).instance().handleSubmit()",High,https://callstack.github.io/react-native-testing-library/
|
|
30
|
+
Testing,Mock Native Modules,Mock native modules in jest.setup.js,Setup mocks for native modules in config,Skip tests using native modules,"jest.mock('react-native-keychain' () => ({ setGenericPassword: jest.fn() }))","Skip tests using native modules",Medium,
|
|
31
|
+
Testing,Snapshot Testing,Use snapshot tests sparingly for critical UI,Snapshot for stable component states only,Snapshot everything brittle tests,"expect(render(<Header title='Home' />).toJSON()).toMatchSnapshot()","Snapshot on every component",Low,
|
|
32
|
+
Testing,Detox E2E,Use Detox for end-to-end testing,Detox for critical user flow testing,Manual testing or Appium,"test('login' async () => { await element(by.id('email')).typeText('test@mail.com'); await element(by.id('login')).tap(); })","Manual QA testing only",Medium,https://wix.github.io/Detox/
|
|
33
|
+
Hooks,useEffect Cleanup,Always return cleanup from useEffect,Cleanup subscriptions timers listeners,useEffect without cleanup,"useEffect(() => { const sub = api.subscribe(handler); return () => sub.unsubscribe(); } [])","useEffect(() => { api.subscribe(handler) } []) // no cleanup",Critical,
|
|
34
|
+
Hooks,useEffect Dependencies,List all dependencies in useEffect array,Include every external value used in effect,Empty deps with external values,"useEffect(() => { fetchUser(userId) } [userId])","useEffect(() => { fetchUser(userId) } []) // stale userId",Critical,https://react.dev/reference/react/useEffect
|
|
35
|
+
Hooks,useRef for Mutable Values,Use useRef for non-rendering values,useRef for timers intervals previous values,useState for non-rendering values,"const intervalRef = useRef(null)","const [interval setInterval] = useState(null) // unnecessary render",Medium,
|
|
36
|
+
Hooks,No useEffect for Derived,Compute derived values during render,useMemo for derived data from props/state,useEffect + setState for computed values,"const fullName = useMemo(() => first + ' ' + last [first last])","useEffect(() => { setFullName(first + ' ' + last) } [first last])",High,https://react.dev/learn/you-might-not-need-an-effect
|
|
37
|
+
New Architecture,Enable Fabric,Enable Fabric renderer for concurrent features,Set newArchEnabled=true in gradle.properties,Stay on old architecture for new projects,// android/gradle.properties: newArchEnabled=true; // ios: RCT_NEW_ARCH_ENABLED=1,// Old architecture: Bridge-based async communication,High,https://reactnative.dev/docs/the-new-architecture/landing-page
|
|
38
|
+
New Architecture,TurboModules,Use TurboModules for native module access,Create TurboModule specs for type-safe native access,Use old NativeModules bridge,export interface Spec extends TurboModule { multiply(a: number b: number): number; } export default TurboModuleRegistry.get<Spec>('Calculator'),NativeModules.Calculator.multiply(2 3) // untyped; async bridge,High,https://reactnative.dev/docs/the-new-architecture/pillars-turbomodules
|
|
39
|
+
Expo,Expo Router,Use Expo Router for file-based routing,Create file-based routes in app/ directory,Manual React Navigation configuration,// app/(tabs)/index.tsx -> automatic tab route; app/[id].tsx -> dynamic route,const Stack = createNativeStackNavigator(); <Stack.Navigator><Stack.Screen name='Home' ... /></Stack.Navigator>,Medium,https://docs.expo.dev/router/introduction/
|
|
40
|
+
Expo,Expo Prebuild,Use Expo Prebuild for native project management,Use config plugins instead of manual native changes,Eject and manually edit iOS/Android projects,// app.config.js: { plugins: [['expo-camera' { cameraPermission: 'Allow camera' }]] },// Manually edit AndroidManifest.xml and Info.plist,Medium,https://docs.expo.dev/workflow/prebuild/
|
|
41
|
+
State,Zustand Store,Use Zustand for simple efficient state management,Create small focused stores with selectors,Single monolithic Redux store for everything,const useAuthStore = create((set) => ({ user: null login: (user) => set({ user }) logout: () => set({ user: null }) })),const store = configureStore({ reducer: { auth: authReducer ui: uiReducer nav: navReducer /* 20 more */ } }),Medium,https://zustand-demo.pmnd.rs/
|
|
42
|
+
State,Jotai Atoms,Use Jotai for fine-grained atomic state,Create atoms for individual state pieces,Re-render entire subtree on any state change,const countAtom = atom(0); const doubleAtom = atom((get) => get(countAtom) * 2); const [count setCount] = useAtom(countAtom),const [state setState] = useState({ count: 0 name: '' items: [] }) // all re-render,Medium,https://jotai.org/
|
|
43
|
+
Performance,useMemo useCallback,Use memoization for expensive computations and callbacks,Memoize values and callbacks that are passed to child components,Create new functions and objects every render,const sortedItems = useMemo(() => items.sort(compareFn) [items]); const onPress = useCallback(() => select(id) [id]),const sortedItems = items.sort(compareFn); const onPress = () => select(id); // recreated every render,High,https://react.dev/reference/react/useMemo
|
|
44
|
+
Performance,React Compiler,Enable React Compiler for automatic memoization,Use React Compiler (React 19+) for auto memo,Manually wrap everything in useMemo useCallback React.memo,// babel.config.js: plugins: [['babel-plugin-react-compiler']] // auto-memoizes,const MemoComp = React.memo(Comp); const cb = useCallback(() => {} []); // manual everywhere,Medium,https://react.dev/learn/react-compiler
|
|
45
|
+
TypeScript,Strict Types,Enable strict TypeScript for type safety,Use strict mode with no-any rules,Use any or loose types throughout,interface User { id: number; name: string; email: string }; const getUser = async (id: number): Promise<User> => ...,const getUser = async (id: any): Promise<any> => { const resp: any = await fetch(...) },High,https://www.typescriptlang.org/tsconfig/#strict
|
|
46
|
+
TypeScript,Zod Validation,Use Zod for runtime type validation,Validate API responses with Zod schemas,Trust API responses match TypeScript types,const UserSchema = z.object({ id: z.number() name: z.string() }); const user = UserSchema.parse(response.data),const user = response.data as User; // no runtime validation; may crash later,Medium,https://zod.dev/
|
|
47
|
+
UI,NativeWind Styling,Use NativeWind for Tailwind-like styling,Apply utility classes for rapid consistent styling,Write StyleSheet for every component,<View className='flex-1 bg-white p-4'><Text className='text-lg font-bold'>Hello</Text></View>,<View style={styles.container}><Text style={styles.title}>Hello</Text></View> // verbose,Medium,https://www.nativewind.dev/
|
|
48
|
+
UI,React Native Skia,Use React Native Skia for advanced graphics,Use Skia for custom drawing animations and image processing,Use Canvas or SVG for complex graphics,const { Canvas Path } = require('@shopify/react-native-skia'); <Canvas><Path path={path} color='blue' /></Canvas>,<Svg><Path d='...' /></Svg> // limited animation; not GPU-accelerated,Medium,https://shopify.github.io/react-native-skia/
|
|
49
|
+
Navigation,Stack with Gestures,Configure native stack with proper gesture handling,Use native stack navigator with gesture enabled,Use JS-based stack navigator,<Stack.Navigator screenOptions={{ animation: 'slide_from_right' gestureEnabled: true }}><Stack.Screen ... /></Stack.Navigator>,<Stack.Navigator screenOptions={{ animationEnabled: false }}> // no gestures; jarring,Medium,https://reactnavigation.org/docs/native-stack-navigator
|
|
50
|
+
Testing,React Native Testing Library,Use RNTL for component testing,Test components from user perspective with queries,Use enzyme or shallow rendering,const { getByText getByTestId } = render(<LoginScreen />); fireEvent.press(getByText('Login')); expect(getByText('Welcome')).toBeTruthy(),const wrapper = shallow(<LoginScreen />); expect(wrapper.find('Button').length).toBe(1) // implementation detail,High,https://callstack.github.io/react-native-testing-library/
|
|
51
|
+
Testing,MSW for API Mocking,Use MSW for API mocking in tests,Set up mock service worker for realistic API testing,Mock fetch or axios directly,const server = setupServer(rest.get('/api/user' (req res ctx) => res(ctx.json({ name: 'John' })))); beforeAll(() => server.listen()),jest.mock('axios' () => ({ get: jest.fn(() => Promise.resolve({ data: mockData })) })) // brittle,Medium,https://mswjs.io/
|
|
52
|
+
Error Handling,Error Boundary,Wrap screens in Error Boundary components,Add ErrorBoundary at screen and critical component level,Let errors crash entire app,<ErrorBoundary FallbackComponent={ErrorFallback}><Screen /></ErrorBoundary>,// No error boundary; one component error crashes entire app,Critical,https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary
|
|
53
|
+
Accessibility,Accessibility Props,Add accessibility props to all interactive elements,Use accessibilityLabel accessibilityRole accessibilityHint,Leave interactive elements without accessibility props,<TouchableOpacity accessibilityLabel='Add to cart' accessibilityRole='button' accessibilityHint='Adds item to shopping cart'>,<TouchableOpacity onPress={addToCart}><Image source={cartIcon} /></TouchableOpacity> // silent to screen reader,High,https://reactnative.dev/docs/accessibility
|
|
54
|
+
Build,EAS Build,Use EAS Build for cloud builds,Use EAS Build with build profiles for development preview production,Build locally on each developer machine,// eas.json: { build: { production: { distribution: 'store' } preview: { distribution: 'internal' } } },npx react-native run-ios --configuration Release // local builds; inconsistent environments,Medium,https://docs.expo.dev/build/introduction/
|
|
55
|
+
Storage,MMKV Storage,Use MMKV for high-performance key-value storage,Use MMKV instead of AsyncStorage for better performance,Use AsyncStorage for frequently accessed data,import { MMKV } from 'react-native-mmkv'; const storage = new MMKV(); storage.set('token' jwt),await AsyncStorage.setItem('token' jwt) // 30x slower than MMKV,High,https://github.com/mrousavy/react-native-mmkv
|
|
56
|
+
Monitoring,Flipper Integration,Use Flipper for development debugging and inspection,Enable Flipper plugins for network layout and React DevTools,Use console.log for all debugging,// Already included in React Native; Enable Layout Inspector Network Inspector React DevTools,console.log(JSON.stringify(response)) // no structured debugging,Low,https://fbflipper.com/
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Template Name,Platform,Architecture,Tech Stack,Modules,Folder Structure,Features Included,Key Dependencies,Reference URL
|
|
2
|
+
E-commerce Android,Android,MVVM + Clean,Compose|Hilt|Room|Retrofit|Coil,app|core|feature-products|feature-cart|feature-auth,Multi-module,Auth|Products|Cart|Checkout|Profile|Search,hilt-android|room-runtime|retrofit2|coil-compose|navigation-compose|paging3,https://developer.android.com/topic/architecture
|
|
3
|
+
Social Media Android,Android,MVI,Compose|Koin|Realm|Ktor|Coil,app|shared|feature-feed|feature-chat|feature-profile,Feature-based,Feed|Stories|Chat|Profile|Notifications|Search,koin-android|ktor-client|realm-kotlin|coil-compose|exoplayer,https://developer.android.com/topic/architecture/ui-layer
|
|
4
|
+
Banking Android,Android,Clean Architecture,Compose|Hilt|Room|Retrofit|DataStore,app|core|data|domain|presentation,Clean layers,Dashboard|Transfers|Cards|Settings|Biometric,hilt-android|room|retrofit2|datastore|biometric|encrypted-preferences,https://developer.android.com/topic/modularization
|
|
5
|
+
Fitness Android,Android,MVVM + Repository,Compose|Hilt|Room|Retrofit,app|data|ui,Standard,Workouts|Progress|Nutrition|Social|Settings,hilt-android|room|retrofit2|health-connect|mpandroidchart,https://developer.android.com/health-and-fitness/guides
|
|
6
|
+
News Android,Android,MVI + Paging,Compose|Hilt|Room|Retrofit|Paging3,app|core|feature-home|feature-detail|feature-bookmark,Multi-module,Feed|Article Detail|Bookmarks|Categories|Search,paging3|room|retrofit2|hilt|coil-compose,https://developer.android.com/topic/libraries/architecture/paging/v3-overview
|
|
7
|
+
E-commerce iOS,iOS,MVVM-C,SwiftUI|Combine|URLSession|SwiftData,App|Core|Features|Navigation,Coordinator-based,Products|Cart|Checkout|Profile|Search,Kingfisher|SwiftData|KeychainAccess|Stripe,https://developer.apple.com/documentation/swiftui
|
|
8
|
+
Banking iOS,iOS,VIPER,SwiftUI|Combine|Swinject|CoreData,App|Modules|Core|Services,Module-based,Dashboard|Transfers|Cards|Settings|FaceID,Swinject|KeychainAccess|CoreData|LocalAuthentication,https://developer.apple.com/documentation/localauthentication
|
|
9
|
+
Social Media iOS,iOS,TCA,SwiftUI|ComposableArchitecture|Dependencies,App|Features|Core|Clients,TCA Feature-based,Feed|Stories|DMs|Profile|Notifications,ComposableArchitecture|Nuke|swift-dependencies,https://github.com/pointfreeco/swift-composable-architecture
|
|
10
|
+
Healthcare iOS,iOS,MVVM + Router,SwiftUI|Combine|HealthKit,App|Views|ViewModels|Services|Models,Standard MVVM,Appointments|Records|Medications|Chat|Profile,HealthKit|Charts|KeychainAccess,https://developer.apple.com/documentation/healthkit
|
|
11
|
+
Productivity iOS,iOS,Clean Swift VIP,SwiftUI|Combine|CoreData,App|Scenes|Workers|Models,Scene-based,Tasks|Calendar|Notes|Settings|Widgets,CoreData|WidgetKit|CloudKit,https://developer.apple.com/documentation/widgetkit
|
|
12
|
+
Delivery Flutter,Flutter,BLoC,Flutter|Bloc|Dio|Hive|GoogleMaps,lib/features|lib/core|lib/shared,Feature-first,Orders|Tracking|Map|Profile|History,flutter_bloc|dio|hive|google_maps_flutter|geolocator,https://pub.dev/packages/google_maps_flutter
|
|
13
|
+
E-commerce Flutter,Flutter,Riverpod + Clean,Flutter|Riverpod|Dio|Drift|GoRouter,lib/data|lib/domain|lib/presentation|lib/core,Clean layers,Products|Cart|Checkout|Auth|Profile,flutter_riverpod|dio|drift|go_router|cached_network_image,https://riverpod.dev/
|
|
14
|
+
Chat App Flutter,Flutter,BLoC + Firebase,Flutter|Bloc|Firebase|Hive,lib/features|lib/core|lib/config,Feature-first,Messaging|Groups|Contacts|Profile|Calls,flutter_bloc|firebase_core|cloud_firestore|firebase_auth,https://firebase.google.com/docs/flutter/setup
|
|
15
|
+
Education Flutter,Flutter,Provider + Clean,Flutter|Provider|Dio|SQFlite,lib/data|lib/domain|lib/presentation,Clean layers,Courses|Videos|Quizzes|Progress|Profile,provider|dio|sqflite|video_player|flutter_cache_manager,https://pub.dev/packages/video_player
|
|
16
|
+
Food Delivery RN,React Native,Redux Toolkit,RN|ReduxToolkit|Axios|AsyncStorage|Maps,src/features|src/store|src/services,Feature-based,Menu|Cart|Orders|Tracking|Profile,@reduxjs/toolkit|axios|react-native-maps|@react-navigation/native,https://reactnavigation.org/docs/getting-started
|
|
17
|
+
Social Media RN,React Native,Zustand,RN|Zustand|Axios|MMKV,src/stores|src/screens|src/components,Store-based,Feed|Stories|Chat|Profile|Explore,zustand|axios|react-native-mmkv|react-native-reanimated,https://zustand-demo.pmnd.rs/
|
|
18
|
+
Fitness RN,React Native,Context + React Query,RN|ReactQuery|Context|Axios|Realm,src/contexts|src/screens|src/api,Context-based,Workouts|Nutrition|Progress|Social|Settings,@tanstack/react-query|axios|realm|react-native-health,https://tanstack.com/query/latest
|
|
19
|
+
Streaming RN,React Native,MobX,RN|MobX|Axios|AsyncStorage,src/stores|src/screens|src/services,MobX stores,Browse|Player|Downloads|Profile|Search,mobx|mobx-react-lite|axios|react-native-video,https://mobx.js.org/
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
Product Type,Platform,Keywords,Recommended Arch,Recommended UI,Color Mood,Key Features,Anti Patterns,Key Dependencies,Notes,Reference URL
|
|
2
|
+
E-commerce,Android,"ecommerce shop store products cart checkout buy sell retail",MVVM + Clean Architecture,Jetpack Compose + Material3,Vibrant primary + success green,Products|Cart|Checkout|Search|Reviews|Wishlist,God Activity|No pagination|Blocking main thread,Hilt|Room|Retrofit|Coil|Navigation Compose|Paging3,Use Paging3 for product lists Coil for images,https://developer.android.com/topic/architecture
|
|
3
|
+
E-commerce,iOS,"ecommerce shop store products cart checkout buy sell retail",MVVM-C,SwiftUI + Combine,Vibrant primary + success green,Products|Cart|Checkout|Search|Reviews|Wishlist,Force unwrapping|No error handling|Massive VC,SwiftData|Kingfisher|KeychainAccess|Stripe,Use async/await for networking SwiftData for persistence,https://developer.apple.com/documentation/swiftui
|
|
4
|
+
E-commerce,Flutter,"ecommerce shop store products cart checkout buy sell retail",BLoC + Clean,Material3 + Custom Widgets,Vibrant primary + success green,Products|Cart|Checkout|Search|Reviews|Wishlist,setState everywhere|No state management|Widget rebuild,flutter_bloc|dio|drift|go_router|cached_network_image,Use BLoC for state Dio for networking,https://bloclibrary.dev/
|
|
5
|
+
E-commerce,React Native,"ecommerce shop store products cart checkout buy sell retail",Redux Toolkit,React Native Paper + Custom,Vibrant primary + success green,Products|Cart|Checkout|Search|Reviews|Wishlist,Prop drilling|Re-render hell|No optimization,@reduxjs/toolkit|axios|@react-navigation/native|react-native-mmkv,Use RTK Query for API caching FlashList for lists,https://redux-toolkit.js.org/
|
|
6
|
+
Banking,Android,"banking finance money transfer dashboard accounts security",Clean Architecture + Multi-Module,Compose + Material3 + Biometric,Professional blue + trust,Dashboard|Transfers|Cards|Settings|Biometric Auth,Hardcoded secrets|No encryption|Plain SharedPreferences,Hilt|Room|Retrofit|EncryptedSharedPreferences|Biometric,Implement biometric auth encrypt all stored data,https://developer.android.com/topic/modularization
|
|
7
|
+
Banking,iOS,"banking finance money transfer dashboard accounts security",VIPER,SwiftUI + UIKit hybrid,Professional blue + trust,Dashboard|Transfers|Cards|Settings|FaceID,Singletons|Global state|No keychain,CoreData|Swinject|KeychainAccess|LocalAuthentication,Use Keychain for tokens FaceID for auth,https://github.com/infinum/iOS-VIPER-Xcode-Templates
|
|
8
|
+
Banking,Flutter,"banking finance money transfer dashboard accounts security",BLoC + Clean,Material3 + Custom Theme,Professional blue + trust,Dashboard|Transfers|Cards|Settings|Biometric,No encryption|setState for auth|Plain storage,flutter_bloc|dio|flutter_secure_storage|local_auth|drift,Use flutter_secure_storage never SharedPreferences for tokens,https://bloclibrary.dev/
|
|
9
|
+
Banking,React Native,"banking finance money transfer dashboard accounts security",Redux Toolkit + RTK Query,React Native Paper,Professional blue + trust,Dashboard|Transfers|Cards|Settings|Biometric,Plain AsyncStorage for tokens|No SSL pinning,@reduxjs/toolkit|axios|react-native-keychain|react-native-biometrics,Use Keychain wrapper for secure storage,https://redux-toolkit.js.org/
|
|
10
|
+
Social Media,Android,"social media feed stories chat posts likes followers",MVI,Compose + Animations + Coil,Energetic vibrant playful,Feed|Stories|Chat|Profile|Notifications|Search,Memory leaks|No image caching|Blocking UI,Koin|Ktor|Room|Coil|ExoPlayer|Firebase,Use Coil for images ExoPlayer for video content,https://developer.android.com/topic/architecture/ui-layer
|
|
11
|
+
Social Media,iOS,"social media feed stories chat posts likes followers",MVVM-C + Combine,SwiftUI + Custom Animations,Energetic vibrant playful,Feed|Stories|Chat|Profile|Notifications|Search,Retain cycles|No image caching|No pagination,Nuke|AVFoundation|Combine|Firebase,Use Nuke for image loading optimize list performance,https://developer.apple.com/documentation/swiftui
|
|
12
|
+
Social Media,Flutter,"social media feed stories chat posts likes followers",BLoC + Firebase,Material3 + Custom Widgets,Energetic vibrant playful,Feed|Stories|Chat|Profile|Notifications|Search,Widget rebuild storm|No dispose|No pagination,flutter_bloc|firebase_core|cloud_firestore|cached_network_image,Use Firebase for real-time BLoC for state,https://firebase.google.com/docs/flutter/setup
|
|
13
|
+
Social Media,React Native,"social media feed stories chat posts likes followers",Zustand + React Query,React Native + Reanimated,Energetic vibrant playful,Feed|Stories|Chat|Profile|Notifications|Search,Re-render hell|No cleanup|Large bundle,zustand|@tanstack/react-query|react-native-reanimated|react-native-fast-image,Use Reanimated for animations FlashList for feed,https://zustand-demo.pmnd.rs/
|
|
14
|
+
Healthcare,Android,"healthcare medical health patient appointment doctor records",MVVM + Clean,Compose + Material3 + Accessibility,Calming blue-green + trust,Appointments|Records|Medications|Chat|Profile,Poor accessibility|No encryption|Missing error handling,Hilt|Room|Retrofit|EncryptedSharedPreferences|Health Connect,HIPAA compliance accessibility mandatory,https://developer.android.com/guide/topics/ui/accessibility
|
|
15
|
+
Healthcare,iOS,"healthcare medical health patient appointment doctor records",MVVM + Router,SwiftUI + Accessibility,Calming blue-green + trust,Appointments|Records|Medications|Chat|Profile,No VoiceOver|No encryption|Force unwrap,HealthKit|KeychainAccess|Charts,Accessibility mandatory support VoiceOver,https://developer.apple.com/documentation/healthkit
|
|
16
|
+
Healthcare,Flutter,"healthcare medical health patient appointment doctor records",Riverpod + Clean,Material3 + Accessible Theme,Calming blue-green + trust,Appointments|Records|Medications|Chat|Profile,No semantics|No secure storage|No validation,flutter_riverpod|dio|flutter_secure_storage|health,Add Semantics widgets proper form validation,https://riverpod.dev/
|
|
17
|
+
Healthcare,React Native,"healthcare medical health patient appointment doctor records",Context + React Query,React Native Paper + Accessible,Calming blue-green + trust,Appointments|Records|Medications|Chat|Profile,Missing accessibility props|No secure storage,@tanstack/react-query|react-native-keychain|react-native-health,Implement proper accessibility roles and labels,https://tanstack.com/query/latest
|
|
18
|
+
Delivery,Android,"delivery food logistics tracking map driver rider order",MVVM + Repository,Compose + Google Maps,Energetic orange + action,Orders|Tracking|Map|Profile|History|Ratings,No location optimization|Battery drain|No offline,Hilt|Retrofit|Room|Google Maps SDK|Location Services,Optimize location updates for battery,https://developers.google.com/maps/documentation/android-sdk
|
|
19
|
+
Delivery,iOS,"delivery food logistics tracking map driver rider order",MVVM-C,SwiftUI + MapKit,Energetic orange + action,Orders|Tracking|Map|Profile|History|Ratings,Continuous location drain|No caching|No offline,MapKit|CoreLocation|Combine,Use significant location changes when possible,https://developer.apple.com/documentation/mapkit
|
|
20
|
+
Delivery,Flutter,"delivery food logistics tracking map driver rider order",BLoC,Material3 + Google Maps,Energetic orange + action,Orders|Tracking|Map|Profile|History|Ratings,No battery optimization|setState for location,flutter_bloc|google_maps_flutter|geolocator|dio,Use geolocator with distance filter,https://pub.dev/packages/google_maps_flutter
|
|
21
|
+
Delivery,React Native,"delivery food logistics tracking map driver rider order",Redux Toolkit,React Native Maps,Energetic orange + action,Orders|Tracking|Map|Profile|History|Ratings,High frequency location updates|No background handling,@reduxjs/toolkit|react-native-maps|@react-native-community/geolocation,Optimize location polling frequency,https://github.com/react-native-maps/react-native-maps
|
|
22
|
+
Fitness,Android,"fitness workout exercise gym health tracker progress",MVVM + Repository,Compose + MPAndroidChart,Energetic green + motivating,Workouts|Progress|Nutrition|Social|Settings,No Health Connect|Memory leaks with sensors,Hilt|Room|Retrofit|Health Connect|MPAndroidChart,Integrate Health Connect for health data,https://developer.android.com/health-and-fitness/guides
|
|
23
|
+
Fitness,iOS,"fitness workout exercise gym health tracker progress",MVVM,SwiftUI + Charts,Energetic green + motivating,Workouts|Progress|Nutrition|Social|Settings,No HealthKit|Battery drain with tracking,HealthKit|Charts|CoreMotion|WidgetKit,Use HealthKit background delivery for updates,https://developer.apple.com/documentation/healthkit
|
|
24
|
+
Fitness,Flutter,"fitness workout exercise gym health tracker progress",Riverpod,Material3 + fl_chart,Energetic green + motivating,Workouts|Progress|Nutrition|Social|Settings,No health integration|No chart optimization,flutter_riverpod|health|fl_chart|dio,Use health package for cross-platform health data,https://pub.dev/packages/health
|
|
25
|
+
Fitness,React Native,"fitness workout exercise gym health tracker progress",Zustand,React Native + Victory Charts,Energetic green + motivating,Workouts|Progress|Nutrition|Social|Settings,No native health bridge|Poor chart performance,zustand|react-native-health|victory-native|react-native-reanimated,Bridge to HealthKit/Health Connect natively,
|
|
26
|
+
Education,Android,"education learning course video quiz student teacher",MVVM + Clean,Compose + ExoPlayer,Calm blue + learning,Courses|Videos|Quizzes|Progress|Certificates,No offline mode|No video caching|Poor DRM,Hilt|Room|Retrofit|ExoPlayer|WorkManager,Implement offline download with WorkManager,https://developer.android.com/media/media3/exoplayer
|
|
27
|
+
Education,iOS,"education learning course video quiz student teacher",MVVM-C,SwiftUI + AVKit,Calm blue + learning,Courses|Videos|Quizzes|Progress|Certificates,No offline|No picture-in-picture|No caching,AVKit|CoreData|CloudKit,Support PiP and AirPlay for video content,https://developer.apple.com/documentation/avkit
|
|
28
|
+
Education,Flutter,"education learning course video quiz student teacher",BLoC + Clean,Material3 + video_player,Calm blue + learning,Courses|Videos|Quizzes|Progress|Certificates,No offline|No video preloading|Widget rebuilds,flutter_bloc|video_player|dio|hive|flutter_cache_manager,Cache video content for offline viewing,https://pub.dev/packages/video_player
|
|
29
|
+
Education,React Native,"education learning course video quiz student teacher",Redux Toolkit,React Native Paper,Calm blue + learning,Courses|Videos|Quizzes|Progress|Certificates,No offline|Bundle size from video player,@reduxjs/toolkit|react-native-video|axios|react-native-fs,Pre-download content for offline access,https://github.com/TheWidlarzGroup/react-native-video
|
|
30
|
+
Chat,Android,"chat messaging instant real-time conversation group",MVI + Clean,Compose + WebSocket,Modern teal + communication,Messaging|Groups|Contacts|Calls|Media|Status,No message persistence|WebSocket leak|No pagination,Hilt|Room|OkHttp WebSocket|Coil|Firebase,Use Room for message cache WebSocket for real-time,https://developer.android.com/training/data-storage/room
|
|
31
|
+
Chat,iOS,"chat messaging instant real-time conversation group",TCA,SwiftUI + URLSessionWebSocketTask,Modern teal + communication,Messaging|Groups|Contacts|Calls|Media|Status,No local cache|Retain cycles|No pagination,ComposableArchitecture|CoreData|Nuke,Use CoreData for persistence URLSession for WebSocket,https://github.com/pointfreeco/swift-composable-architecture
|
|
32
|
+
Chat,Flutter,"chat messaging instant real-time conversation group",BLoC + Firebase,Material3 + Custom Bubbles,Modern teal + communication,Messaging|Groups|Contacts|Calls|Media|Status,No offline cache|setState for messages|Memory leaks,flutter_bloc|cloud_firestore|firebase_auth|hive,Use Firestore for real-time Hive for local cache,https://firebase.google.com/docs/firestore
|
|
33
|
+
Chat,React Native,"chat messaging instant real-time conversation group",Zustand + React Query,Gifted Chat + Custom,Modern teal + communication,Messaging|Groups|Contacts|Calls|Media|Status,No message persistence|WebSocket not cleaned up,zustand|socket.io-client|react-native-gifted-chat|watermelondb,Use WatermelonDB for local SQLite cache,https://watermelondb.dev/
|
|
34
|
+
Travel,Android,travel hotel flight booking map itinerary schedule reservation,MVVM + Clean Architecture,Compose + Google Maps + Material3,Wanderlust blue + sunset orange,Search|Booking|Map|Itinerary|Reviews|Offline,No offline mode|Blocking UI with network calls|No map caching,Hilt|Room|Retrofit|Google Maps SDK|WorkManager|Paging3,Offline-first for itineraries. Cache map tiles. Use Paging3 for search results.,https://developer.android.com/topic/architecture
|
|
35
|
+
Travel,iOS,travel hotel flight booking map itinerary schedule reservation,MVVM-C + SwiftUI,SwiftUI + MapKit,Wanderlust blue + sunset orange,Search|Booking|Map|Itinerary|Reviews|Offline,No MapKit optimization|Force unwrap API responses|No offline,SwiftData|MapKit|Combine|StoreKit,Use SwiftData for offline itineraries. MapKit annotations for POIs.,https://developer.apple.com/documentation/mapkit
|
|
36
|
+
Travel,Flutter,travel hotel flight booking map itinerary schedule reservation,BLoC + Clean,Material3 + Google Maps,Wanderlust blue + sunset orange,Search|Booking|Map|Itinerary|Reviews|Offline,No caching|setState for complex booking state|No error handling,flutter_bloc|google_maps_flutter|dio|hive|go_router,Use Hive for offline itinerary storage. Bloc for booking flow.,https://bloclibrary.dev/
|
|
37
|
+
Travel,React Native,travel hotel flight booking map itinerary schedule reservation,Zustand + React Query,React Native Maps + Paper,Wanderlust blue + sunset orange,Search|Booking|Map|Itinerary|Reviews|Offline,No offline sync|Re-render heavy maps|Memory leaks,zustand|@tanstack/react-query|react-native-maps|react-native-mmkv,MMKV for fast offline storage. React Query for search caching.,https://zustand-demo.pmnd.rs/
|
|
38
|
+
Music Streaming,Android,music streaming audio playlist song player background,MVI + Clean,Compose + Media3 + Custom Player,Vibrant purple + dark mode,Player|Playlists|Search|Library|Downloads|Equalizer,No background playback handling|Memory leaks with ExoPlayer|No audio focus,Hilt|Room|Retrofit|Media3 ExoPlayer|MediaSession|WorkManager,Use MediaSession for controls. Handle audio focus. Background playback service.,https://developer.android.com/media/media3
|
|
39
|
+
Music Streaming,iOS,music streaming audio playlist song player background,TCA,SwiftUI + AVFoundation + Custom,Vibrant purple + dark mode,Player|Playlists|Search|Library|Downloads|Equalizer,No background audio handling|No Now Playing info|Retain cycles,ComposableArchitecture|AVFoundation|MediaPlayer|CoreData,Set MPNowPlayingInfoCenter. Handle interruptions. Background audio mode.,https://github.com/pointfreeco/swift-composable-architecture
|
|
40
|
+
Music Streaming,Flutter,music streaming audio playlist song player background,BLoC + Clean,Material3 + Custom Audio Player,Vibrant purple + dark mode,Player|Playlists|Search|Library|Downloads|Equalizer,No background audio|No notification controls|Widget rebuild,flutter_bloc|just_audio|audio_service|hive|dio,Use audio_service for background playback. just_audio for player.,https://pub.dev/packages/just_audio
|
|
41
|
+
Music Streaming,React Native,music streaming audio playlist song player background,Redux Toolkit,React Native Paper + Custom,Vibrant purple + dark mode,Player|Playlists|Search|Library|Downloads|Equalizer,No background audio|No media controls|Memory leaks,@reduxjs/toolkit|react-native-track-player|react-native-fs,Use track-player for queue management and background playback.,https://rntp.dev/
|
|
42
|
+
News,Android,news article magazine feed read later offline categories,MVVM + Repository,Compose + Material3 + Paging3,Professional gray + accent red,Feed|Categories|Read Later|Search|Notifications|Offline,No pagination|No offline articles|Blocking main thread,Hilt|Room|Retrofit|Paging3|WorkManager|Coil,Paging3 for feed. Room for offline articles. WorkManager for sync.,https://developer.android.com/topic/libraries/architecture/paging/v3-overview
|
|
43
|
+
News,iOS,news article magazine feed read later offline categories,MVVM + Router,SwiftUI + Combine,Professional gray + accent red,Feed|Categories|Read Later|Search|Notifications|Offline,No pagination|Massive view controllers|No caching,SwiftData|Combine|Kingfisher|WidgetKit,SwiftData for offline. WidgetKit for headlines widget. Combine for reactive feed.,https://developer.apple.com/documentation/widgetkit
|
|
44
|
+
Real Estate,Android,real estate property listing map search filter house apartment,MVVM + Clean,Compose + Google Maps + Material3,Trust navy + premium gold,Listings|Map View|Search|Favorites|Virtual Tour|Calculator,No map clustering|Memory leaks with images|No filter optimization,Hilt|Room|Retrofit|Google Maps SDK|Coil|Paging3,Map clustering for listings. Coil for property images. Paging3 for search.,https://developers.google.com/maps/documentation/android-sdk/utility
|
|
45
|
+
Real Estate,iOS,real estate property listing map search filter house apartment,MVVM-C,SwiftUI + MapKit,Trust navy + premium gold,Listings|Map View|Search|Favorites|Virtual Tour|Calculator,No MapKit clustering|Poor image performance|No offline,MapKit|SwiftData|Kingfisher|ARKit,Use MapKit annotations with clustering. ARKit for virtual tours.,https://developer.apple.com/documentation/arkit
|
|
46
|
+
Ride Sharing,Android,ride sharing taxi cab driver passenger map route tracking,MVVM + Clean,Compose + Google Maps + Material3,Safety green + night dark,Map|Booking|Tracking|Payment|History|Rating,Excessive location polling|No battery optimization|No WebSocket handling,Hilt|Retrofit|Google Maps SDK|Location Services|OkHttp WebSocket,Fused location for efficiency. WebSocket for real-time tracking. Foreground service.,https://developer.android.com/develop/sensors-and-location/location
|
|
47
|
+
Ride Sharing,Flutter,ride sharing taxi cab driver passenger map route tracking,BLoC + Clean,Material3 + Google Maps Flutter,Safety green + night dark,Map|Booking|Tracking|Payment|History|Rating,No battery optimization|setState for location|No background service,flutter_bloc|google_maps_flutter|geolocator|web_socket_channel|dio,Geolocator with distance filter. WebSocket for driver tracking.,https://pub.dev/packages/geolocator
|
|
48
|
+
IoT Smart Home,Android,iot smart home device control automation sensor bluetooth wifi,MVVM + Repository,Compose + Material3 + Custom Controls,Modern teal + warm ambient,Devices|Rooms|Automation|Scenes|Notifications|Settings,No BLE handling|No offline device state|Polling instead of events,Hilt|Room|Retrofit|Bluetooth LE|MQTT|WorkManager,Use BLE for local control. MQTT for cloud. Room for device state cache.,https://developer.android.com/guide/topics/connectivity/bluetooth/ble-overview
|
|
49
|
+
IoT Smart Home,iOS,iot smart home device control automation sensor bluetooth wifi homekit,MVVM,SwiftUI + HomeKit,Modern teal + warm ambient,Devices|Rooms|Automation|Scenes|Siri|Settings,No HomeKit integration|No accessory pairing|Poor BLE handling,HomeKit|CoreBluetooth|CloudKit|WidgetKit,Use HomeKit for Apple ecosystem. CoreBluetooth for custom devices.,https://developer.apple.com/documentation/homekit
|
|
50
|
+
IoT Smart Home,Flutter,iot smart home device control bluetooth wifi automation flutter,BLoC + Clean,Material3 + Custom Widgets,Modern teal + warm ambient,Devices|Rooms|Automation|Scenes|Notifications|Settings,No BLE plugin|setState for device state|No offline queue,flutter_bloc|flutter_reactive_ble|hive|mqtt_client|go_router,Use flutter_reactive_ble for Bluetooth. HiveDB for device state cache.,https://pub.dev/packages/flutter_reactive_ble
|
|
51
|
+
IoT Smart Home,React Native,iot smart home device control bluetooth wifi automation react native,Zustand + React Query,React Native Paper + Custom,Modern teal + warm ambient,Devices|Rooms|Automation|Scenes|Notifications|Settings,No BLE cleanup|Global mutable state|Polling instead of MQTT,zustand|react-native-ble-plx|react-native-mmkv|mqtt.js,Use BLE PLX for Bluetooth devices. MQTT for real-time cloud communication.,https://github.com/dotintent/react-native-ble-plx
|
|
52
|
+
News,Flutter,news article magazine feed read later offline dart flutter,BLoC + Clean,Material3 + Custom Cards,Professional gray + accent red,Feed|Categories|Read Later|Search|Notifications|Offline,No pagination|setState for feed|No caching,flutter_bloc|dio|hive|infinite_scroll_pagination|cached_network_image,Use infinite_scroll_pagination for feed. Hive for offline articles.,https://pub.dev/packages/infinite_scroll_pagination
|
|
53
|
+
News,React Native,news article magazine feed read later react native,Zustand + React Query,React Native Paper + Custom,Professional gray + accent red,Feed|Categories|Read Later|Search|Notifications|Offline,No pagination|Excessive re-renders|No offline,zustand|@tanstack/react-query|react-native-mmkv|@shopify/flash-list,FlashList for feed performance. React Query for caching. MMKV for read later.,https://shopify.github.io/flash-list/
|
|
54
|
+
Real Estate,Flutter,real estate property listing map search flutter dart,BLoC + Clean,Material3 + Google Maps Flutter,Trust navy + premium gold,Listings|Map View|Search|Favorites|Virtual Tour|Calculator,No map marker clustering|setState for filters|Memory leaks,flutter_bloc|google_maps_flutter|dio|cached_network_image|flutter_map_marker_cluster,Use marker clustering for performance. Cached images for property photos.,https://pub.dev/packages/google_maps_flutter
|
|
55
|
+
Real Estate,React Native,real estate property listing map search react native,Zustand + React Query,React Native Maps + Paper,Trust navy + premium gold,Listings|Map View|Search|Favorites|Virtual Tour|Calculator,No map clustering|No image optimization|Re-render on scroll,zustand|@tanstack/react-query|react-native-maps|react-native-fast-image,Use SuperCluster for map clustering. FastImage for property photos.,https://github.com/react-native-maps/react-native-maps
|
|
56
|
+
Ride Sharing,iOS,ride sharing taxi cab driver passenger map route tracking ios,MVVM-C,SwiftUI + MapKit,Safety green + night dark,Map|Booking|Tracking|Payment|History|Rating,No background location mode|Force unwrap coordinates|No battery optimization,MapKit|CoreLocation|Combine|StoreKit|URLSession,Use CLLocationManager with allowsBackgroundLocationUpdates. MapKit for route display.,https://developer.apple.com/documentation/corelocation
|
|
57
|
+
Ride Sharing,React Native,ride sharing taxi cab driver passenger map route tracking react native,Redux Toolkit,React Native Maps + Paper,Safety green + night dark,Map|Booking|Tracking|Payment|History|Rating,No background location|Excessive re-renders on location update|No WebSocket,@reduxjs/toolkit|react-native-maps|react-native-background-geolocation|socket.io-client,Background geolocation for driver tracking. Socket.io for real-time updates.,https://github.com/transistorsoft/react-native-background-geolocation
|