Core Principles

This section covers the foundational architectural decisions that govern the Zima project.

Clean Architecture

The Zima project is built on a foundation of Clean Architecture. This approach separates the code into distinct layers, promoting separation of concerns and making the app easier to manage and scale.

The primary layers are:

  1. Presentation: The UI layer, containing all widgets, screens, and UI-specific state management (Controllers).

  2. Application: The business logic layer, containing services and providers that orchestrate the application's features. It acts as a bridge between the Presentation and Data layers.

  3. Data: The data handling layer, responsible for fetching data from remote APIs (Remote Data Source) and caching it locally (Local Data Source). It uses the Repository pattern to abstract the origin of the data.

Folder Structure

The project uses a feature-first folder structure. All the code related to a specific feature (like auth, onboarding, or agent) is grouped together in its own directory under lib/.

lib/
├── app/              # Shared widgets, constants, and providers
├── agent/            # Core feature: Interacting with the AI agent
├── auth/             # User authentication (login, registration)
├── home/             # Main screen after login, agent list
├── onboarding/       # Splash screen and initial user onboarding flow
└── main.dart         # App entry point and routing

Each feature folder follows the Clean Architecture structure.

feature_name/
├── application/      # Business logic (Services, Controllers, Providers)
├── data/             # Data handling (Repositories, Data Sources, Models)
├── presentation/     # UI components (Screens, Widgets, Bars, etc.)
└── models/           # Domain models specific to the feature

[Placeholder for a diagram illustrating the Clean Architecture layers and the feature-based folder structure.]

State Management

The application uses the Provider package for state management.

  • ChangeNotifierProvider is used to provide instances of our controllers and providers to the widget tree.

  • Consumer and ListenableBuilder widgets are used to listen to changes and rebuild the UI accordingly.

  • We use a Controller-Provider pattern where a Controller (ChangeNotifier) holds the state and business logic, and a separate ControllerProvider (ChangeNotifier) manages the lifecycle of that controller. This is clearly visible in the agent and onboarding modules.

Last updated