A production-ready Flutter app built with FakeStoreAPI, Retrofit, Dio, Cubit, and Clean Architecture — structured the way real companies build scalable mobile apps.
- ✅ Clean Architecture (Data / Domain / Presentation)
- ✅ Retrofit for type-safe, annotation-driven API calls
- ✅ Dio HTTP client with timeout and logging
- ✅ Cubit (flutter_bloc) for predictable state management
- ✅ GetIt dependency injection
- ✅ Repository pattern for full abstraction
- ✅ Product CRUD: Get All · Add · Delete
- ✅ Real-time client-side search by title & category
- ✅ Shimmer skeleton loading
- ✅ Staggered grid animations
- ✅ Cached network images
- ✅ Beautiful, responsive UI with Google Fonts
| Layer | Technology |
|---|---|
| Language | Dart |
| Framework | Flutter |
| Networking | Dio + Retrofit |
| State Management | flutter_bloc (Cubit) |
| Dependency Injection | GetIt |
| Code Generation | build_runner, json_serializable, retrofit_generator |
| UI | Google Fonts, Shimmer, Staggered Animations |
| API | FakeStoreAPI |
Base URL: https://fakestoreapi.com
| Method | Endpoint | Description |
|---|---|---|
GET |
/products |
Fetch all products |
POST |
/products |
Add a new product |
DELETE |
/products/{id} |
Delete a product by ID |
lib/
├── main.dart
│
├── core/
│ ├── di/
│ │ └── injection.dart ← GetIt DI registration
│ ├── errors/
│ │ ├── failures.dart ← Domain failures (Server, Network)
│ │ └── error_handler.dart ← Exception mapping & Developer logging
│ └── networks/
│ ├── api_service.dart ← Retrofit interface (@GET, @POST, @DELETE)
│ └── api_service.g.dart ← Generated Retrofit implementation
│
└── features/
└── products/
├── data/
│ ├── datasources/
│ │ └── product_remote_datasource.dart
│ ├── mappers/
│ │ └── product_mapper.dart ← Model ↔ Entity mappers
│ ├── models/
│ │ ├── product_request_model.dart
│ │ ├── product_response_model.dart
│ │ └── rating_model.dart
│ └── repositories/
│ └── product_repository_impl.dart
│
├── domain/
│ ├── entities/
│ │ └── product.dart ← Pure Dart entity (Equatable)
│ ├── params/
│ │ └── add_product_params.dart ← Use Case parameters
│ ├── repositories/
│ │ └── product_repository.dart ← Abstract contract
│ └── usecases/
│ ├── get_product.dart
│ ├── add_product.dart
│ └── delete_product.dart
│
└── presentation/
├── pages/
│ ├── product_page.dart ← Screens
│ └── local_widgets/ ← UI Components
│ ├── add_product_sheet.dart
│ ├── product_app_bar.dart
│ ├── product_card.dart
│ ├── product_error_view.dart
│ ├── product_grid.dart
│ ├── product_search_bar.dart
│ └── product_shimmer_grid.dart
└── state/
├── product_cubit.dart
└── product_state.dart
git clone https://github.com/your-username/retrofit-store-flutter.git
cd retrofit-store-flutterflutter pub getdart run build_runner build --delete-conflicting-outputsRe-run this command whenever you modify
api_service.dartor any@JsonSerializablemodel.
flutter run@RestApi(baseUrl: 'https://fakestoreapi.com')
abstract class ApiService {
factory ApiService(Dio dio) = _ApiService;
@GET('/products')
Future<List<ProductModel>> getProducts();
@POST('/products')
Future<ProductModel> addProduct(@Body() Map<String, dynamic> product);
@DELETE('/products/{id}')
Future<dynamic> deleteProduct(@Path('id') int id);
}No manual URL building. No manual JSON parsing. No repetitive boilerplate — Retrofit generates everything via build_runner.
UI (Cubit/State)
↓
Use Cases (Params) ← [Params] encapsulate input data for business logic
↓
Repository ← Abstract contract (Interface)
↓
Repository Impl ← Uses [Mappers] to bridge Data and Domain
↓
Datasource ← Fetches raw data from external sources
↓
Retrofit + Dio ← Handles HTTP requests and JSON parsing
Each layer only knows about the layer directly below it. The domain layer has zero Flutter or Retrofit dependencies.
dependencies:
dio: ^5.4.3+1
retrofit: ^4.1.0
json_annotation: ^4.9.0
get_it: ^7.7.0
flutter_bloc: ^8.1.6
equatable: ^2.0.5
cached_network_image: ^3.3.1
flutter_staggered_animations: ^1.1.1
shimmer: ^3.0.0
google_fonts: ^6.2.1
dev_dependencies:
retrofit_generator: ^8.1.0
build_runner: ^2.4.9
json_serializable: ^6.8.0- How Clean Architecture is applied in a real Flutter app
- How Retrofit eliminates boilerplate API code with annotations
- How Cubit manages state cleanly across loading / loaded / error
- How GetIt wires all dependencies without context
- How to break a page into small, focused local widgets
- How the Repository pattern decouples your UI from your data source
Built as part of a daily Flutter learning series focused on production-level architecture, clean code, and real-world patterns.
If this helped you, give it a star on GitHub ⭐
Flutter Dart Clean Architecture Retrofit Dio Cubit flutter_bloc GetIt FakeStoreAPI Mobile Development 100DaysOfFlutter