In this article series, I will show you how to build a production-grade Habit Tracker application using Flutter.
We will focus on creating a scalable architecture that follows industry best practices. My goal is to explain these concepts in simple words so that anyone can follow along and build a high-quality app for their portfolio.
The Series Roadmap
We have divided this project into 5 parts:
The Foundation (This Article): Setting up the architecture, dependencies, and navigation.
Authentication: Integrating Supabase for secure user login and sign-up.
Core Features: Implementing the habit management logic (CRUD).
Advanced Logic: Handling streaks, daily tracking, and local notifications.
UI & Visualization: Adding charts and final polish to the user interface.
1. Clean Architecture
In many simple projects, developers write all the code in a few files. However, for a production app, we use Clean Architecture. We divide our code into layers so that each part has a specific responsibility.
The structure we will follow is:
Domain Layer: This is the most important part. It contains our business rules and logic. It is independent of any external database or UI.
Data Layer: This layer handles the data fetching from APIs or databases (like Supabase). It implements the interfaces defined in the domain layer.
Presentation Layer: This is where our UI lives. It uses BLoC to manage the state and display information to the user.
Our folder structure in lib/will look like this:
lib/
├── core/ # Shared utilities, theme, and router
├── features/ # Each feature (auth, habit, stats)
│ ├── [feature_name]/
│ │ ├── data/ # API calls and models
│ │ ├── domain/ # Business rules and entities
│ │ └── presentation/ # UI widgets and BLoCs
├── injection_container.dart # For dependency management
└── main.dart # Entry point of the app
Essential Dependencies
To build a professional app, we need to use some standard packages. Here are the main dependencies we have added to our pubspec.yaml:
dependencies:
flutter_bloc: ^8.1.3 # For state management
supabase_flutter: ^1.10.0 # Our backend-as-a-service
get_it: ^7.6.0 # For dependency injection
go_router: ^12.0.0 # For modern navigation
google_fonts: ^6.1.0 # For better typography
3. Dependency Injection (DI)
Dependency Injection is a very useful concept in software engineering. Instead of creating objects manually inside every class, we use a "Service Locator" to manage them. We are using the get_itpackage for this purpose. In lib/injection_container.dart, we register all our classes:
final sl = GetIt.instance; // sl stands for Service Locator
Future<void> init() async {
// Registering Core Services
sl.registerLazySingleton(() => NotificationService());
// Registering Auth Feature
sl.registerFactory(() => AuthBloc(signIn: sl()));
sl.registerLazySingleton(() => SignIn(sl()));
sl.registerLazySingleton<AuthRepository>(() => AuthRepositoryImpl(sl()));
}
This approach makes our code much easier to test and maintain in the long run.
4. Navigation with GoRouter
For moving between different screens, we use go_router. It is very robust and handles deep-linking very well. We define all our routes in a central place:
final router = GoRouter(
initialLocation: '/splash',
routes: [
GoRoute(path: '/splash', builder: (context, state) => const SplashPage()),
GoRoute(path: '/login', builder: (context, state) => const LoginPage()),
// ... other routes
],
);
5. Design System and Theming
To ensure the app looks professional, we have created a centralized theme using Material 3. This helps in maintaining a consistent look and feel across all pages.
class AppTheme {
static ThemeData get light {
return ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFF6B4EFF),
brightness: Brightness.light,
),
textTheme: GoogleFonts.outfitTextTheme(),
);
}
}
Conclusion
We have successfully set up the foundation of our project. We have a clear architecture, necessary dependencies, and a solid navigation system. It is very important to get these things right at the start.
In the next article, we will discuss how to integrate Supabase for user authentication. Please stay tuned for Part 2!