Clean Architecture Implementation
Relevant source files
The following files were used as context for generating this wiki page:
The MoodTune application utilizes a robust Clean Architecture pattern to ensure separation of concerns, testability, and maintainability. The system is structured into three primary layers per feature—Presentation, Domain, and Data—where dependencies strictly point inward. This architecture facilitates the integration of complex services like Spotify OAuth, Supabase authentication, and FastAPI-based audio analysis while keeping the core business logic decoupled from external frameworks and data sources.
Sources: CLAUDE.md:46-47, authplan.md:14-25
Layered Structure and Responsibilities
The application organizes code into three distinct layers. This structure is replicated across all core features including Authentication, Analysis, and Spotify integration.
Data Layer
The Data Layer is responsible for communicating with external data sources. It includes RemoteDataSources that use HTTP clients (Dio) to talk to the backend, Models for JSON deserialization with .toDomain() extensions, and Repositories that implement domain contracts while mapping low-level exceptions to domain-specific failures.
Sources: CLAUDE.md:61-65, authplan.md:23-25
Domain Layer
This is the central layer containing pure Dart code with no framework dependencies. It houses Entities (using Equatable for immutability), Repository interfaces, and UseCases that encapsulate single business operations. The domain layer defines the contracts that the data layer must fulfill.
Sources: CLAUDE.md:67-71, authplan.md:20-22
Presentation Layer
The Presentation Layer handles UI and state management. It utilizes the BLoC (Business Logic Component) pattern for state handling, featuring a single state class with copyWith and enum-based status tracking. It consists of Pages (routes), Widgets (reusable components), and BLoCs.
Sources: CLAUDE.md:73-77, CLAUDE.md:92-96, authplan.md:17-19
The following diagram illustrates the inward-pointing dependency flow:
Diagram showing the flow from UI through Business Logic to Data acquisition.
Sources: CLAUDE.md:46-47, authplan.md:14-25
Core System Components
Dependency Injection and Service Locator
The project uses GetIt as a service locator for dependency injection. The configureDependencies() function is called during the application bootstrap to register singletons for Dio clients, repositories, and use cases. A specific tokenProvider lambda is used to capture Supabase session tokens dynamically for authenticated requests.
Sources: CLAUDE.md:104-107, authplan.md:243-255
Error Handling Pattern
Errors are handled using a functional approach with the dartz package. Repositories and Use Cases return a ResultFuture<T>, which is a type alias for Future<Either<Failure, T>>.
| Component | Responsibility |
|---|---|
Exception | Thrown by DataSources (e.g., ServerException, CacheException) |
Failure | Returned by Repositories (e.g., ServerFailure, AuthFailure) |
fold() | Used by BLoCs to handle either the Failure or the Success result |
Sources: CLAUDE.md:82-90, authplan.md:188-195
Navigation and Routing
Routing is implemented using go_router with a centralized AppRouter. The navigation is "Authentication-Aware," meaning the router reacts to authentication state changes via a refreshListenable and automatically redirects users between public (login/signup) and protected (home/history) routes.
Sequence of authentication-aware redirection logic.
Sources: routing_plan.md:32-42, routing_plan.md:225-248
Feature Implementation: Authentication
The Authentication feature serves as a primary example of this Clean Architecture in practice. It integrates Supabase for email/password and OAuth (Google/Apple) flows.
Auth Data Flow
- RemoteDataSource: Communicates with Supabase using
supabase_flutter. - Repository: Validates internet connection and maps Supabase
Userobjects toUserModeland then to theUserEntity. - Use Case:
LoginUseCaseorGoogleSignInUseCaseexecutes the specific repository method. - BLoC:
AuthBloctriggers the use case and emitsAuthenticatedorUnauthenticatedstates.
Sources: authplan.md:130-170, authplan.md:213-228
Key Auth Components
| Class | Layer | Purpose |
|---|---|---|
User | Domain | Pure entity representing the user profile |
AuthRepository | Domain | Abstract contract for all auth operations |
SupabaseAuthService | Data | Direct interaction with Supabase SDK |
TokenStorage | Core/Data | Securely stores JWTs using FlutterSecureStorage |
Sources: authplan.md:68-83, authplan.md:180-188, authplan.md:231-237
Summary
The Clean Architecture implementation in MoodTune ensures that the complex audio analysis and music catalog logic remains isolated from the UI and external SDKs. By enforcing strict dependency rules and utilizing patterns like BLoC for state and Either for error handling, the codebase maintains high technical standards for scalability and testing.
Sources: CLAUDE.md:46-77, README.md:83-93