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!

