A modern cryptocurrency and NFT tracking application built with Flutter, demonstrating Clean Architecture principles and best practices in modern mobile development.
| Market | NFT |
|---|---|
![]() |
![]() |
- 💰 Cryptocurrency Tracking – Real-time crypto market data from CoinGecko
- 🎨 NFT Marketplace – Browse NFT collections via Reservoir API
- ⭐ Favorites System – Save and manage your favorite coins and NFTs
- 🔐 Authentication – Secure user authentication with Supabase
- 📊 Detailed Analytics – View comprehensive coin and NFT details
- 🌙 Theme Support – Light and dark mode
- 📱 Responsive Design – Optimized for all screen sizes
This project follows Clean Architecture principles with clear separation of concerns across three layers:
lib/
├── core/ # Shared utilities and base classes
│ ├── di/ # Dependency injection (GetIt)
│ ├── routing/ # Navigation configuration (GoRouter)
│ ├── theme/ # App theming
│ ├── widgets/ # Shared widgets
│ ├── logger/ # Logging utilities
│ ├── utils/ # Helper functions & retry strategies
│ └── exceptions/ # Custom exceptions
├── features/ # Feature modules
│ ├── coin/ # Cryptocurrency feature
│ │ ├── data/ # Data layer
│ │ │ ├── coin_repository_impl.dart # Repository implementation
│ │ │ ├── coin_mapper.dart # Data mapping
│ │ │ └── coin_service.dart # API service (legacy)
│ │ ├── domain/ # Business logic layer
│ │ │ ├── coin.dart # Domain entity
│ │ │ └── coin_repository.dart # Repository interface
│ │ └── presentation/ # UI layer
│ │ ├── pages/ # Screens
│ │ ├── bloc/ # BLoC for state management
│ │ └── widgets/ # Feature-specific widgets
│ ├── auth/ # Authentication feature
│ │ ├── data/ # Auth service & data layer
│ │ ├── domain/ # User model
│ │ └── presentation/ # Login/Signup pages & Cubit
│ ├── profile/ # User profile feature
│ └── globalmarket/ # Global market data feature
Data Layer
- API services for external data sources
- Data models with JSON serialization
- Repository implementations
- Local storage management
Domain Layer
- Business entities
- Repository interfaces
- Use cases (business logic)
Presentation Layer
- UI screens and widgets
- Riverpod providers for state management
- View models
Core
- Flutter SDK:
3.9+ - Dart:
3.9.2+ - Architecture: Clean Architecture
- State Management: BLoC / Cubit (flutter_bloc)
- DI Container: GetIt
- Navigation: GoRouter
Key Dependencies
| Package | Purpose |
|---|---|
flutter_bloc |
State management (BLoC/Cubit pattern) |
get_it |
Service locator & dependency injection |
go_router |
Declarative routing & navigation |
fpdart |
Functional programming (Either for error handling) |
supabase_flutter |
Backend-as-a-Service (Auth + Database) |
http |
HTTP client for API requests |
equatable |
Value equality for BLoC states |
shared_preferences |
Local data persistence |
Free cryptocurrency data API providing:
- Market data for 10,000+ cryptocurrencies
- Price charts and historical data
- Market statistics and trends
- No API key required
Base URL: https://api.coingecko.com/api/v3/
NFT marketplace aggregator providing:
- NFT collection data
- Floor prices and sales
- Collection metadata
Base URL: https://api.reservoir.tools/
(May require API key for production)
Used for:
- User authentication (email/password)
- Session management
- Database operations
- Flutter SDK 3.9 or higher
- Dart 3.9.2 or higher
- iOS Simulator / Android Emulator or physical device
- Supabase account (for authentication features)
git clone https://github.com/teasec4/flutter-crypto-app.git
cd flutter-crypto-appflutter pub getCreate file lib/core/secrets/app_secrets.dart:
class AppSecrets {
static const String supabaseUrl = 'YOUR_SUPABASE_URL';
static const String supabaseAnonKey = 'YOUR_SUPABASE_ANON_KEY';
}Get your credentials from Supabase:
- Create a new project
- Go to Settings → API
- Copy the Project URL and anon/public key
flutter run📱 Android
flutter build apk --release
# or
flutter build appbundle --release🍎 iOS
flutter build ios --releasevoid setupServiceLocator() {
// Register repositories
getIt.registerSingleton<CoinRepository>(CoinRepositoryImpl());
// Register BLoCs/Cubits
getIt.registerSingleton<CoinBloc>(
CoinBloc(getIt<CoinRepository>(), getIt<RetryStrategy>()),
);
}class CoinBloc extends Bloc<CoinEvent, CoinState> {
CoinBloc(this._repo, this._retryStrategy) : super(const CoinInitial()) {
on<CoinInitialLoad>(_onInitialLoad);
on<CoinLoadMore>(_onLoadMore);
}
Future<void> _onInitialLoad(CoinInitialLoad event, Emitter<CoinState> emit) async {
emit(const CoinLoading());
try {
final coins = await _repo.getCoins(page: 1, perPage: 30);
emit(CoinLoaded(coins: coins));
} catch (e) {
emit(CoinError(e.toString()));
}
}
}class AuthCubit extends Cubit<AuthState> {
AuthCubit(this._service) : super(const AuthInitial());
Future<void> signIn({required String email, required String password}) async {
emit(const AuthLoading());
final result = await _service.signIn(email: email, password: password);
result.match(
(failure) => emit(AuthError(failure.message)),
(user) => emit(AuthAuthenticated(user)),
);
}
}GoRouter(
redirect: (context, state) {
final authState = getIt<AuthCubit>().state;
final isAuthenticated = authState is AuthAuthenticated;
// Smart redirects based on auth state
},
routes: [
GoRoute(path: '/coins', builder: (context, state) => const CoinPage()),
GoRoute(
path: '/coins/details/:id',
builder: (context, state) {
final coin = state.extra as Coin;
return CoinDetailPage(coin: coin);
},
),
],
);✅ Clean Architecture – Proper separation of concerns
✅ BLoC/Cubit Pattern – Scalable state management
✅ GetIt – Service locator for dependency injection
✅ Go Router – Type-safe declarative navigation
✅ Repository Pattern – Clean data abstraction layer
✅ Functional Programming – Either type for error handling
✅ Supabase Integration – Firebase alternative for Auth & Database
✅ API Integration – REST API consumption with proper error handling
✅ Retry Strategy – Exponential backoff for resilient requests
✅ Authentication Guards – Route protection based on auth state
# Run all tests
flutter test
# Run with coverage
flutter test --coverage
# Run integration tests
flutter test integration_test- Browse cryptocurrency market
- Search and filter coins
- View detailed coin information
- Price charts and statistics
- Add to favorites
- Explore NFT collections
- View collection details
- Floor prices and volume
- Metadata display
- Save favorite coins & NFTs
- Local persistence
- Quick access to saved items
- Email/password authentication
- Session management
- Protected routes
- User profile
Example environment config:
class EnvConfig {
static const bool isProduction = bool.fromEnvironment('dart.vm.product');
static const String apiBaseUrl = String.fromEnvironment(
'API_BASE_URL',
defaultValue: 'https://api.coingecko.com/api/v3/',
);
}Run with:
flutter run --dart-define=API_BASE_URL=https://your-api.com- Fork the project
- Create a feature branch:
git checkout -b feature/AmazingFeature
- Commit your changes:
git commit -m 'Add some AmazingFeature' - Push to the branch:
git push origin feature/AmazingFeature
- Open a Pull Request
This project was created for educational purposes.
teasec4
- GitHub: @teasec4
- CoinGecko – for free crypto API
- Reservoir – for NFT data
- Supabase – for backend services
- Flutter & Dart communities for excellent tools
⭐️ If this project helped you learn Flutter and Clean Architecture, give it a star!

