Skip to content

πŸš€ User management app built in flutter using clean architecture, MVVM, get it, dio, RxDart, bloc, cubit, getX and provider + Unit Testing

License

Notifications You must be signed in to change notification settings

SinaSys/flutter_go_rest_app

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ”₯ Go Rest app

Flutter User Management App with Multi-Source Backend Support

This project is a Flutter-based user management application that demonstrates full CRUD (Create, Read, Update, Delete) operations. The app interacts with a RESTful API to manage users and their associated data, including posts, todos, and comments.

A key feature of this application is its flexible backend architecture. Developers can seamlessly switch between two data sources:

  1. The public GoRest API (https://gorest.co.in/)
  2. A custom, self-hosted backend built with Spring Boot and Kotlin

This choice is managed through environment variables, putting the decision of which backend to use entirely in the hands of the user.

Features

  • User Management: Browse, add, edit, and delete user profiles.
  • User Content: View and manage detailed user information, including their posts, todos, and comments.
  • API Operations: Utilizes all standard HTTP methods (GET, POST, PUT, DELETE) to interact with the API endpoints.
  • Backend Agnostic: Configure the app to run against the free GoRest service or your own private Kotlin/Spring Boot backend for full control and offline development.

Technology Stack

  • Frontend: Flutter
  • Backend Options:
    • GoRest API: A free-to-use online REST API.
    • Custom Backend: Spring Boot with Kotlin and PostgreSQL, replicating the GoRest functionality.

πŸ–Ό Screenshots

User screen Create-update User Todo screen Post screen
Date picker Time picker Create-update post Comment Screen
Error state Empty state Warning dialog Progress dialog

🧩 Entity Relationship Diagram (ERD)

πŸš€ Features

  • Different implementations with separate modules based on state management solutions and software architectures

  • Clean architecture / MVVM architecture / simple layered architecture

  • Feature-first and Layer-first approach

  • Performing CRUD operation using Dio and go rest api

  • Converting JSON string to an equivalent dart object and vice versa with json serializable

  • Implementing Interceptors, Global configuration and timeout for api calls

  • Exception Handling with Dio interceptor, Dartz and freezed

  • Dependency injection with get it (Clean architecture / MVVM architecture version)

  • Displaying error type to the user through the alert dialogs

  • Colorize api info like request, response, body and exceptions in Debug console log

  • Read, create, update and delete user

  • Filter users by status activity or gender

  • Read, create, update and delete user todos

  • Filter todos by status

  • Read, create, update and delete user posts

  • Display, create and delete user comments for each post

  • Get date/time from user by Date/Time picker

  • Generic structure

  • State management with GetX | Bloc | Cubit | RxDart

  • Unit testing (Clean architecture version (GetX))


🀝 Feature-first (Package-by-feature) and Layer-first (Package-by-layer)

In this repository two architectural approaches have been used. Feature-first (for clean architecture and simple layered architecture version) and Layer-first (for mvvm architecture version).

The feature-first approach demands that we create a new folder for every new feature that we add to our app. And inside that, we add the layers themselves as sub-folders. But in Layer-first approach, we add all the relevant files inside each feature folder, ensuring that they belong to the correct layer.


⚠️ API Limitations (GoREST)

When using the GoREST API, there are some important limitations to be aware of:


Fixed Number of Users

  • The users endpoint always contains 10 user objects by default.
  • If any of them are deleted, they are automatically replaced with new placeholder data.
  • As a result:
    • The user list will always remain 10 items long.
    • It is not possible to create more than 10 users.
    • Query parameters on the users endpoint are limited in functionality.

Authorization Required for Write Operations

  • To use PUT, POST, PATCH, or DELETE requests, an access token must be provided in the Authorization header as a Bearer token.
  • A token has already been included in the app configuration.
  • If a 401 Unauthorized error occurs, a new token must be requested here and updated in the api_config file located in the core directory.

Temporary Data

  • The API data is not permanent.
  • It is refreshed or cleared every 20 minutes to 1 hour, meaning any changes will not persist for long.

βœ… No Limitations with the Custom Backend

When using the custom Spring Boot backend, all of the above limitations are removed:

  • Unlimited creation and management of users, posts, todos, and comments.
  • No external access token is required.
  • Data is stored in a real PostgreSQL database and persists permanently.




πŸ§ͺ Coverage (Clean Architecture Version (GetX))




πŸ—‚ Modules

Version Bloc Cubit Getx RxDart + Provider
Clean architecture version Source️ Source Source Source
MVVM architecture version Source Source️ Source️
Simple layered architecture version Source Source Source

πŸ“š Dependencies (Clean architecture version (Feature-first))

Name GetX Cubit Bloc RxDart + Provider
flutter_bloc βœ–οΈ βœ” βœ” βœ–
provider βœ–οΈ βœ– βœ– βœ”
rxdart βœ–οΈ βœ– βœ– βœ”
get_it βœ”οΈ βœ” βœ” βœ”
GetX βœ”οΈ βœ–οΈ βœ–οΈ βœ–
dio βœ”οΈ βœ”οΈ βœ”οΈ βœ”
freezed βœ–οΈ βœ”οΈ βœ”οΈ βœ”
freezed_annotation βœ– βœ”οΈ βœ”οΈ βœ”
json_annotation βœ”οΈ βœ”οΈ βœ”οΈ βœ”
json_serializable βœ”οΈ βœ”οΈ βœ”οΈ βœ”
build_runner βœ”οΈ βœ”οΈ βœ”οΈ βœ”
logger βœ”οΈ βœ”οΈ βœ”οΈ βœ”
dartz βœ”οΈ βœ–οΈ βœ–οΈ βœ–
flutter_spinkit βœ”οΈ βœ”οΈ βœ”οΈ βœ”
intl βœ”οΈ βœ”οΈ βœ”οΈ βœ”
mockito βœ”οΈ βœ–οΈ βœ–οΈ βœ–


πŸ“š Dependencies (MVVM architecture version (Layer-first))

Name GetX Cubit Bloc
flutter_bloc βœ–οΈ βœ” βœ”
get_it βœ”οΈ βœ” βœ”
GetX βœ”οΈ βœ–οΈ βœ–οΈ
dio βœ”οΈ βœ”οΈ βœ”οΈ
freezed βœ–οΈ βœ”οΈ βœ”οΈ
freezed_annotation βœ– βœ”οΈ βœ”οΈ
json_annotation βœ”οΈ βœ”οΈ βœ”οΈ
json_serializable βœ”οΈ βœ”οΈ βœ”οΈ
build_runner βœ”οΈ βœ”οΈ βœ”οΈ
logger βœ”οΈ βœ”οΈ βœ”οΈ
dartz βœ”οΈ βœ–οΈ βœ–οΈ
flutter_spinkit βœ”οΈ βœ”οΈ βœ”οΈ
intl βœ”οΈ βœ”οΈ βœ”οΈ

πŸ“š Dependencies (Simple layered architecture version (Feature-first))

Name GetX Cubit Bloc
flutter_bloc βœ–οΈ βœ” βœ”
GetX βœ”οΈ βœ–οΈ βœ–οΈ
dio βœ”οΈ βœ”οΈ βœ”οΈ
freezed βœ–οΈ βœ”οΈ βœ”οΈ
freezed_annotation βœ– βœ”οΈ βœ”οΈ
json_annotation βœ”οΈ βœ”οΈ βœ”οΈ
json_serializable βœ”οΈ βœ”οΈ βœ”οΈ
build_runner βœ”οΈ βœ”οΈ βœ”οΈ
logger βœ”οΈ βœ”οΈ βœ”οΈ
dartz βœ”οΈ βœ–οΈ βœ–οΈ
flutter_spinkit βœ”οΈ βœ”οΈ βœ”οΈ
intl βœ”οΈ βœ”οΈ βœ”οΈ



πŸ“‚ Directory Structure (Clean architecture version + Bloc)

πŸ“‚lib
│───main.dart  
│───di.dart  
β”‚β”€β”€β”€πŸ“‚common  
β”‚   β”‚β”€β”€β”€πŸ“‚bloc
β”‚   β”‚   │──bloc_helper.dart
β”‚   β”‚   │──generic_bloc_state.dart
β”‚   β”‚   └──generic_bloc_builder.dart
β”‚   β”‚β”€β”€β”€πŸ“‚usecase
β”‚   β”‚   └──usecase.dart
β”‚   β”‚β”€β”€β”€πŸ“‚repository
β”‚   β”‚   └──repository_helper.dart
β”‚   β”‚β”€β”€β”€πŸ“‚network
β”‚   β”‚   │──api_config.dart
β”‚   β”‚   │──api_helper.dart
β”‚   β”‚   │──api_result.dart
β”‚   β”‚   │──api_result.freezed.dart
β”‚   β”‚   │──dio_client.dart
β”‚   β”‚   │──dio_exception.dart
β”‚   β”‚   └──dio_interceptor.dart
β”‚   β”‚β”€β”€β”€πŸ“‚widget
β”‚   β”‚   │──date_time_picker.dart
β”‚   β”‚   │──drop_down.dart
β”‚   β”‚   │──empty_widget.dart
β”‚   β”‚   │──popup_menu.dart
β”‚   β”‚   │──spinkit_indicator.dart
β”‚   β”‚   └──text_input.dart
β”‚   β””β”€β”€β”€πŸ“‚dialog
β”‚       │──create_dialog.dart
β”‚       │──delete_dialog.dart
β”‚       │──progress_dialog.dart
β”‚       └──retry_dialog.dart
β”‚β”€β”€β”€πŸ“‚core
β”‚   │──app_asset.dart
β”‚   │──app_extension.dart
β”‚   │──app_string.dart
β”‚   │──app_style.dart
β”‚   └──app_theme.dart
β”‚
β””β”€β”€β”€πŸ“‚features
    β”‚β”€β”€β”€πŸ“‚user
    β”‚    β”‚β”€β”€β”€πŸ“‚data
    β”‚    β”‚   β”‚β”€β”€πŸ“‚datasources
    β”‚    β”‚   β”‚  └──user_remote_data_source.dart
    β”‚    β”‚   β”‚β”€β”€πŸ“‚models
    β”‚    β”‚   β”‚   │──user.dart
    β”‚    β”‚   β”‚   └──user.g.dart
    β”‚    β”‚   β””β”€β”€πŸ“‚repositories
    β”‚    β”‚       └──user_repository_impl.dart
    β”‚    β”‚β”€β”€β”€πŸ“‚domain
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚entities
    β”‚    β”‚   β”‚   └──user_entity.dart
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚repositories
    β”‚    β”‚   β”‚   └──user_repository.dart
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚usecases
    β”‚    β”‚   β”‚   │──create_user_usecase.dart
    β”‚    β”‚   β”‚   │──delete_user_usecase.dart
    β”‚    β”‚   β”‚   │──get_users_usecase.dart
    β”‚    β”‚   β”‚   └──update_user_usecase.dart
    β”‚    └── πŸ“‚presentation
    β”‚        β”‚β”€β”€β”€πŸ“‚bloc
    β”‚        β”‚   │──user_bloc.dart
    β”‚        β”‚   └──user_event.dart
    β”‚        β”‚β”€β”€β”€πŸ“‚screens
    β”‚        β”‚   └──user_list_screen.dart
    β”‚        β””β”€β”€β”€πŸ“‚widgets
    β”‚            └──status_container.dart
    β”‚
    β”‚β”€β”€β”€πŸ“‚todo
    β”‚    β”‚β”€β”€β”€πŸ“‚data
    β”‚    β”‚   β”‚β”€β”€πŸ“‚datasources
    β”‚    β”‚   β”‚  └──todo_remote_data_source.dart
    β”‚    β”‚   β”‚β”€β”€πŸ“‚models
    β”‚    β”‚   β”‚   │──todo.dart
    β”‚    β”‚   β”‚   └──todo.g.dart
    β”‚    β”‚   β””β”€β”€πŸ“‚repositories
    β”‚    β”‚       └──todo_repository_impl.dart
    β”‚    β”‚β”€β”€β”€πŸ“‚domain
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚entities
    β”‚    β”‚   β”‚   └──todo_entity.dart
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚repositories
    β”‚    β”‚   β”‚   └──todo_repository.dart
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚usecases
    β”‚    β”‚   β”‚   │──create_todo_usecase.dart
    β”‚    β”‚   β”‚   │──delete_todo_usecase.dart
    β”‚    β”‚   β”‚   │──get_todos_usecase.dart
    β”‚    β”‚   β”‚   └──update_todo_usecase.dart
    β”‚    └── πŸ“‚presentation
    β”‚        β”‚β”€β”€β”€πŸ“‚bloc
    β”‚        β”‚   │──todo_bloc.dart
    β”‚        β”‚   └──todo_event.dart
    β”‚        β”‚β”€β”€β”€πŸ“‚screens
    β”‚        β”‚   └──todo_list_screen.dart
    β”‚        β””β”€β”€β”€πŸ“‚widgets
    β”‚            │──circle_container.dart
    β”‚            └──todo_list_item.dart
    β”‚β”€β”€β”€πŸ“‚post
    β”‚    β”‚β”€β”€β”€πŸ“‚data
    β”‚    β”‚   β”‚β”€β”€πŸ“‚datasources
    β”‚    β”‚   β”‚  └──post_remote_data_source.dart
    β”‚    β”‚   β”‚β”€β”€πŸ“‚models
    β”‚    β”‚   β”‚   │──post.dart
    β”‚    β”‚   β”‚   └──post.g.dart
    β”‚    β”‚   β””β”€β”€πŸ“‚repositories
    β”‚    β”‚       └──post_repository_impl.dart
    β”‚    β”‚β”€β”€β”€πŸ“‚domain
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚entities
    β”‚    β”‚   β”‚   └──post_entity.dart
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚repositories
    β”‚    β”‚   β”‚   └──post_repository.dart
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚usecases
    β”‚    β”‚   β”‚   │──create_post_usecase.dart
    β”‚    β”‚   β”‚   │──delete_post_usecase.dart
    β”‚    β”‚   β”‚   │──get_posts_usecase.dart
    β”‚    β”‚   β”‚   └──update_post_usecase.dart
    β”‚    └── πŸ“‚presentation
    β”‚        β”‚β”€β”€β”€πŸ“‚bloc
    β”‚        β”‚   │──post_bloc.dart
    β”‚        β”‚   └──post_event.dart
    β”‚        β””β”€β”€β”€πŸ“‚screens
    β”‚            │──create_post_screen.dart
    β”‚            │──post_detail_screen.dart
    β”‚            └──post_list_screen.dart
    β””β”€β”€β”€πŸ“‚comment
         β”‚β”€β”€β”€πŸ“‚data
         β”‚   β”‚β”€β”€πŸ“‚datasources
         β”‚   β”‚  └──comment_remote_data_source.dart
         β”‚   β”‚β”€β”€πŸ“‚models
         β”‚   β”‚   │──comment.dart
         β”‚   β”‚   └──comment.g.dart
         β”‚   β””β”€β”€πŸ“‚repositories
         β”‚       └──comment_repository_impl.dart
         β”‚β”€β”€β”€πŸ“‚domain
         β”‚   β”‚β”€β”€β”€πŸ“‚entities
         β”‚   β”‚   └──comment_entity.dart
         β”‚   β”‚β”€β”€β”€πŸ“‚repositories
         β”‚   β”‚   └──comment_repository.dart
         β”‚   β”‚β”€β”€β”€πŸ“‚usecases
         β”‚   β”‚   │──create_comment_usecase.dart
         β”‚   β”‚   │──delete_comment_usecase.dart
         β”‚   β”‚   └──get_comments_usecase.dart
         └── πŸ“‚presentation
             β””β”€β”€β”€πŸ“‚bloc
                 │──comment_bloc.dart
                 └──comment_event.dart




πŸ“‚ Directory Structure (Clean architecture version + Cubit)

πŸ“‚lib
│───main.dart  
│───di.dart  
β”‚β”€β”€β”€πŸ“‚common  
β”‚   β”‚β”€β”€β”€πŸ“‚cubit
β”‚   β”‚   │──generic_cubit.dart
β”‚   β”‚   └──generic_cubit_state.dart
β”‚   β”‚β”€β”€β”€πŸ“‚usecase
β”‚   β”‚   └──usecase.dart
β”‚   β”‚β”€β”€β”€πŸ“‚repository
β”‚   β”‚   └──repository_helper.dart
β”‚   β”‚β”€β”€β”€πŸ“‚network
β”‚   β”‚   │──api_config.dart
β”‚   β”‚   │──api_helper.dart
β”‚   β”‚   │──api_result.dart
β”‚   β”‚   │──api_result.freezed.dart
β”‚   β”‚   │──dio_client.dart
β”‚   β”‚   │──dio_exception.dart
β”‚   β”‚   └──dio_interceptor.dart
β”‚   β”‚β”€β”€β”€πŸ“‚widget
β”‚   β”‚   │──date_time_picker.dart
β”‚   β”‚   │──drop_down.dart
β”‚   β”‚   │──empty_widget.dart
β”‚   β”‚   │──popup_menu.dart
β”‚   β”‚   │──spinkit_indicator.dart
β”‚   β”‚   └──text_input.dart
β”‚   β””β”€β”€β”€πŸ“‚dialog
β”‚       │──create_dialog.dart
β”‚       │──delete_dialog.dart
β”‚       │──progress_dialog.dart
β”‚       └──retry_dialog.dart
β”‚β”€β”€β”€πŸ“‚core
β”‚   │──app_asset.dart
β”‚   │──app_extension.dart
β”‚   │──app_string.dart
β”‚   │──app_style.dart
β”‚   └──app_theme.dart
β”‚
β””β”€β”€β”€πŸ“‚features
    β”‚β”€β”€β”€πŸ“‚user
    β”‚    β”‚β”€β”€β”€πŸ“‚data
    β”‚    β”‚   β”‚β”€β”€πŸ“‚datasources
    β”‚    β”‚   β”‚  └──user_remote_data_source.dart
    β”‚    β”‚   β”‚β”€β”€πŸ“‚models
    β”‚    β”‚   β”‚   │──user.dart
    β”‚    β”‚   β”‚   └──user.g.dart
    β”‚    β”‚   β””β”€β”€πŸ“‚repositories
    β”‚    β”‚       └──user_repository_impl.dart
    β”‚    β”‚β”€β”€β”€πŸ“‚domain
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚entities
    β”‚    β”‚   β”‚   └──user_entity.dart
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚repositories
    β”‚    β”‚   β”‚   └──user_repository.dart
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚usecases
    β”‚    β”‚   β”‚   │──create_user_usecase.dart
    β”‚    β”‚   β”‚   │──delete_user_usecase.dart
    β”‚    β”‚   β”‚   │──get_users_usecase.dart
    β”‚    β”‚   β”‚   └──update_user_usecase.dart
    β”‚    └── πŸ“‚presentation
    β”‚        β”‚β”€β”€β”€πŸ“‚cubit
    β”‚        β”‚   └──user_cubit.dart
    β”‚        β”‚β”€β”€β”€πŸ“‚screens
    β”‚        β”‚   └──user_list_screen.dart
    β”‚        β””β”€β”€β”€πŸ“‚widgets
    β”‚            └──status_container.dart
    β”‚
    β”‚β”€β”€β”€πŸ“‚todo
    β”‚    β”‚β”€β”€β”€πŸ“‚data
    β”‚    β”‚   β”‚β”€β”€πŸ“‚datasources
    β”‚    β”‚   β”‚  └──todo_remote_data_source.dart
    β”‚    β”‚   β”‚β”€β”€πŸ“‚models
    β”‚    β”‚   β”‚   │──todo.dart
    β”‚    β”‚   β”‚   └──todo.g.dart
    β”‚    β”‚   β””β”€β”€πŸ“‚repositories
    β”‚    β”‚       └──todo_repository_impl.dart
    β”‚    β”‚β”€β”€β”€πŸ“‚domain
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚entities
    β”‚    β”‚   β”‚   └──todo_entity.dart
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚repositories
    β”‚    β”‚   β”‚   └──todo_repository.dart
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚usecases
    β”‚    β”‚   β”‚   │──create_todo_usecase.dart
    β”‚    β”‚   β”‚   │──delete_todo_usecase.dart
    β”‚    β”‚   β”‚   │──get_todos_usecase.dart
    β”‚    β”‚   β”‚   └──update_todo_usecase.dart
    β”‚    └── πŸ“‚presentation
    β”‚        β”‚β”€β”€β”€πŸ“‚cubit
    β”‚        β”‚   └──todo_cubit.dart
    β”‚        β”‚β”€β”€β”€πŸ“‚screens
    β”‚        β”‚   └──todo_list_screen.dart
    β”‚        β””β”€β”€β”€πŸ“‚widgets
    β”‚            │──circle_container.dart
    β”‚            └──todo_list_item.dart
    β”‚β”€β”€β”€πŸ“‚post
    β”‚    β”‚β”€β”€β”€πŸ“‚data
    β”‚    β”‚   β”‚β”€β”€πŸ“‚datasources
    β”‚    β”‚   β”‚  └──post_remote_data_source.dart
    β”‚    β”‚   β”‚β”€β”€πŸ“‚models
    β”‚    β”‚   β”‚   │──post.dart
    β”‚    β”‚   β”‚   └──post.g.dart
    β”‚    β”‚   β””β”€β”€πŸ“‚repositories
    β”‚    β”‚       └──post_repository_impl.dart
    β”‚    β”‚β”€β”€β”€πŸ“‚domain
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚entities
    β”‚    β”‚   β”‚   └──post_entity.dart
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚repositories
    β”‚    β”‚   β”‚   └──post_repository.dart
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚usecases
    β”‚    β”‚   β”‚   │──create_post_usecase.dart
    β”‚    β”‚   β”‚   │──delete_post_usecase.dart
    β”‚    β”‚   β”‚   │──get_posts_usecase.dart
    β”‚    β”‚   β”‚   └──update_post_usecase.dart
    β”‚    └── πŸ“‚presentation
    β”‚        β”‚β”€β”€β”€πŸ“‚cubit
    β”‚        β”‚   └──post_cubit.dart
    β”‚        β””β”€β”€β”€πŸ“‚screens
    β”‚            │──create_post_screen.dart
    β”‚            │──post_detail_screen.dart
    β”‚            └──post_list_screen.dart
    β””β”€β”€β”€πŸ“‚comment
         β”‚β”€β”€β”€πŸ“‚data
         β”‚   β”‚β”€β”€πŸ“‚datasources
         β”‚   β”‚  └──comment_remote_data_source.dart
         β”‚   β”‚β”€β”€πŸ“‚models
         β”‚   β”‚   │──comment.dart
         β”‚   β”‚   └──comment.g.dart
         β”‚   β””β”€β”€πŸ“‚repositories
         β”‚       └──comment_repository_impl.dart
         β”‚β”€β”€β”€πŸ“‚domain
         β”‚   β”‚β”€β”€β”€πŸ“‚entities
         β”‚   β”‚   └──comment_entity.dart
         β”‚   β”‚β”€β”€β”€πŸ“‚repositories
         β”‚   β”‚   └──comment_repository.dart
         β”‚   β”‚β”€β”€β”€πŸ“‚usecases
         β”‚   β”‚   │──create_comment_usecase.dart
         β”‚   β”‚   │──delete_comment_usecase.dart
         β”‚   β”‚   └──get_comments_usecase.dart
         └── πŸ“‚presentation
             β””β”€β”€β”€πŸ“‚cubit
                 └──comment_cubit.dart




πŸ“‚ Directory Structure (Clean architecture version + RxDart + Provider)

πŸ“‚lib
│───main.dart  
│───di.dart  
β”‚β”€β”€β”€πŸ“‚common  
β”‚   β”‚β”€β”€β”€πŸ“‚bloc
β”‚   β”‚   └──generic_bloc_state.dart
β”‚   β”‚β”€β”€β”€πŸ“‚usecase
β”‚   β”‚   └──usecase.dart
β”‚   β”‚β”€β”€β”€πŸ“‚repository
β”‚   β”‚   └──repository_helper.dart
β”‚   β”‚β”€β”€β”€πŸ“‚network
β”‚   β”‚   │──api_config.dart
β”‚   β”‚   │──api_helper.dart
β”‚   β”‚   │──api_result.dart
β”‚   β”‚   │──api_result.freezed.dart
β”‚   β”‚   │──dio_client.dart
β”‚   β”‚   │──dio_exception.dart
β”‚   β”‚   └──dio_interceptor.dart
β”‚   β”‚β”€β”€β”€πŸ“‚widget
β”‚   β”‚   │──date_time_picker.dart
β”‚   β”‚   │──drop_down.dart
β”‚   β”‚   │──empty_widget.dart
β”‚   β”‚   │──popup_menu.dart
β”‚   β”‚   │──spinkit_indicator.dart
β”‚   β”‚   └──text_input.dart
β”‚   β””β”€β”€β”€πŸ“‚dialog
β”‚       │──create_dialog.dart
β”‚       │──delete_dialog.dart
β”‚       │──progress_dialog.dart
β”‚       └──retry_dialog.dart
β”‚β”€β”€β”€πŸ“‚core
β”‚   │──app_asset.dart
β”‚   │──app_extension.dart
β”‚   │──app_string.dart
β”‚   │──app_style.dart
β”‚   └──app_theme.dart
β”‚
β””β”€β”€β”€πŸ“‚features
    β”‚β”€β”€β”€πŸ“‚user
    β”‚    β”‚β”€β”€β”€πŸ“‚data
    β”‚    β”‚   β”‚β”€β”€πŸ“‚datasources
    β”‚    β”‚   β”‚  └──user_remote_data_source.dart
    β”‚    β”‚   β”‚β”€β”€πŸ“‚models
    β”‚    β”‚   β”‚   │──user.dart
    β”‚    β”‚   β”‚   └──user.g.dart
    β”‚    β”‚   β””β”€β”€πŸ“‚repositories
    β”‚    β”‚       └──user_repository_impl.dart
    β”‚    β”‚β”€β”€β”€πŸ“‚domain
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚entities
    β”‚    β”‚   β”‚   └──user_entity.dart
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚repositories
    β”‚    β”‚   β”‚   └──user_repository.dart
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚usecases
    β”‚    β”‚   β”‚   │──create_user_usecase.dart
    β”‚    β”‚   β”‚   │──delete_user_usecase.dart
    β”‚    β”‚   β”‚   │──get_users_usecase.dart
    β”‚    β”‚   β”‚   └──update_user_usecase.dart
    β”‚    └── πŸ“‚presentation
    β”‚        β”‚β”€β”€β”€πŸ“‚bloc
    β”‚        β”‚   │──user_bloc.dart
    β”‚        β”‚   └──user_event.dart
    β”‚        β”‚β”€β”€β”€πŸ“‚screens
    β”‚        β”‚   └──user_list_screen.dart
    β”‚        β””β”€β”€β”€πŸ“‚widgets
    β”‚            └──status_container.dart
    β”‚
    β”‚β”€β”€β”€πŸ“‚todo
    β”‚    β”‚β”€β”€β”€πŸ“‚data
    β”‚    β”‚   β”‚β”€β”€πŸ“‚datasources
    β”‚    β”‚   β”‚  └──todo_remote_data_source.dart
    β”‚    β”‚   β”‚β”€β”€πŸ“‚models
    β”‚    β”‚   β”‚   │──todo.dart
    β”‚    β”‚   β”‚   └──todo.g.dart
    β”‚    β”‚   β””β”€β”€πŸ“‚repositories
    β”‚    β”‚       └──todo_repository_impl.dart
    β”‚    β”‚β”€β”€β”€πŸ“‚domain
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚entities
    β”‚    β”‚   β”‚   └──todo_entity.dart
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚repositories
    β”‚    β”‚   β”‚   └──todo_repository.dart
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚usecases
    β”‚    β”‚   β”‚   │──create_todo_usecase.dart
    β”‚    β”‚   β”‚   │──delete_todo_usecase.dart
    β”‚    β”‚   β”‚   │──get_todos_usecase.dart
    β”‚    β”‚   β”‚   └──update_todo_usecase.dart
    β”‚    └── πŸ“‚presentation
    β”‚        β”‚β”€β”€β”€πŸ“‚bloc
    β”‚        β”‚   │──todo_bloc.dart
    β”‚        β”‚   └──todo_event.dart
    β”‚        β”‚β”€β”€β”€πŸ“‚screens
    β”‚        β”‚   └──todo_list_screen.dart
    β”‚        β””β”€β”€β”€πŸ“‚widgets
    β”‚            │──circle_container.dart
    β”‚            └──todo_list_item.dart
    β”‚β”€β”€β”€πŸ“‚post
    β”‚    β”‚β”€β”€β”€πŸ“‚data
    β”‚    β”‚   β”‚β”€β”€πŸ“‚datasources
    β”‚    β”‚   β”‚  └──post_remote_data_source.dart
    β”‚    β”‚   β”‚β”€β”€πŸ“‚models
    β”‚    β”‚   β”‚   │──post.dart
    β”‚    β”‚   β”‚   └──post.g.dart
    β”‚    β”‚   β””β”€β”€πŸ“‚repositories
    β”‚    β”‚       └──post_repository_impl.dart
    β”‚    β”‚β”€β”€β”€πŸ“‚domain
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚entities
    β”‚    β”‚   β”‚   └──post_entity.dart
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚repositories
    β”‚    β”‚   β”‚   └──post_repository.dart
    β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚usecases
    β”‚    β”‚   β”‚   │──create_post_usecase.dart
    β”‚    β”‚   β”‚   │──delete_post_usecase.dart
    β”‚    β”‚   β”‚   │──get_posts_usecase.dart
    β”‚    β”‚   β”‚   └──update_post_usecase.dart
    β”‚    └── πŸ“‚presentation
    β”‚        β”‚β”€β”€β”€πŸ“‚bloc
    β”‚        β”‚   └──post_bloc.dart
    β”‚        β””β”€β”€β”€πŸ“‚screens
    β”‚            │──create_post_screen.dart
    β”‚            │──post_detail_screen.dart
    β”‚            └──post_list_screen.dart
    β””β”€β”€β”€πŸ“‚comment
         β”‚β”€β”€β”€πŸ“‚data
         β”‚   β”‚β”€β”€πŸ“‚datasources
         β”‚   β”‚  └──comment_remote_data_source.dart
         β”‚   β”‚β”€β”€πŸ“‚models
         β”‚   β”‚   │──comment.dart
         β”‚   β”‚   └──comment.g.dart
         β”‚   β””β”€β”€πŸ“‚repositories
         β”‚       └──comment_repository_impl.dart
         β”‚β”€β”€β”€πŸ“‚domain
         β”‚   β”‚β”€β”€β”€πŸ“‚entities
         β”‚   β”‚   └──comment_entity.dart
         β”‚   β”‚β”€β”€β”€πŸ“‚repositories
         β”‚   β”‚   └──comment_repository.dart
         β”‚   β”‚β”€β”€β”€πŸ“‚usecases
         β”‚   β”‚   │──create_comment_usecase.dart
         β”‚   β”‚   │──delete_comment_usecase.dart
         β”‚   β”‚   └──get_comments_usecase.dart
         └── πŸ“‚presentation
             β””β”€β”€β”€πŸ“‚bloc
                 └──comment_bloc.dart




πŸ“‚ Directory Structure (Clean architecture version + GetX)

root 
 │── πŸ“‚coverage
 │── πŸ“‚lib
 β”‚   │───main.dart  
 β”‚   │───di.dart  
 β”‚   β”‚β”€β”€β”€πŸ“‚common  
 β”‚   β”‚   β”‚β”€β”€β”€πŸ“‚controller
 β”‚   β”‚   β”‚   └──base_controller.dart
 β”‚   β”‚   β”‚β”€β”€β”€πŸ“‚usecase
 β”‚   β”‚   β”‚   └──usecase.dart
 β”‚   β”‚   β”‚β”€β”€β”€πŸ“‚repository
 β”‚   β”‚   β”‚   └──repository_helper.dart
 β”‚   β”‚   β”‚β”€β”€β”€πŸ“‚network
 β”‚   β”‚   β”‚   │──api_config.dart
 β”‚   β”‚   β”‚   │──api_base.dart
 β”‚   β”‚   β”‚   │──dio_client.dart
 β”‚   β”‚   β”‚   │──dio_exception.dart
 β”‚   β”‚   β”‚   └──dio_interceptor.dart
 β”‚   β”‚   β”‚β”€β”€β”€πŸ“‚widget
 β”‚   β”‚   β”‚   │──date_time_picker.dart
 β”‚   β”‚   β”‚   │──drop_down.dart
 β”‚   β”‚   β”‚   │──empty_widget.dart
 β”‚   β”‚   β”‚   │──popup_menu.dart
 β”‚   β”‚   β”‚   │──spinkit_indicator.dart
 β”‚   β”‚   β”‚   └──text_input.dart
 β”‚   β”‚   β””β”€β”€β”€πŸ“‚dialog
 β”‚   β”‚       │──create_dialog.dart
 β”‚   β”‚       │──delete_dialog.dart
 β”‚   β”‚       │──progress_dialog.dart
 β”‚   β”‚       └──retry_dialog.dart
 β”‚   β”‚β”€β”€β”€πŸ“‚core
 β”‚   β”‚   │──app_asset.dart
 β”‚   β”‚   │──app_extension.dart
 β”‚   β”‚   │──app_string.dart
 β”‚   β”‚   │──app_style.dart
 β”‚   β”‚   └──app_theme.dart
 β”‚   β”‚
 β”‚   β””β”€β”€β”€πŸ“‚features
 β”‚       β”‚β”€β”€β”€πŸ“‚user
 β”‚       β”‚    β”‚β”€β”€β”€πŸ“‚data
 β”‚       β”‚    β”‚   β”‚β”€β”€πŸ“‚datasources
 β”‚       β”‚    β”‚   β”‚  └──user_remote_data_source.dart
 β”‚       β”‚    β”‚   β”‚β”€β”€πŸ“‚models
 β”‚       β”‚    β”‚   β”‚   │──user.dart
 β”‚       β”‚    β”‚   β”‚   └──user.g.dart
 β”‚       β”‚    β”‚   β””β”€β”€πŸ“‚repositories
 β”‚       β”‚    β”‚       └──user_repository_impl.dart
 β”‚       β”‚    β”‚β”€β”€β”€πŸ“‚domain
 β”‚       β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚entities
 β”‚       β”‚    β”‚   β”‚   └──user_entity.dart
 β”‚       β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚repositories
 β”‚       β”‚    β”‚   β”‚   └──user_repository.dart
 β”‚       β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚usecases
 β”‚       β”‚    β”‚   β”‚   │──create_user_usecase.dart
 β”‚       β”‚    β”‚   β”‚   │──delete_user_usecase.dart
 β”‚       β”‚    β”‚   β”‚   │──get_users_usecase.dart
 β”‚       β”‚    β”‚   β”‚   └──update_user_usecase.dart
 β”‚       β”‚    └── πŸ“‚presentation
 β”‚       β”‚        β”‚β”€β”€β”€πŸ“‚controller
 β”‚       β”‚        β”‚   └──user_controller.dart
 β”‚       β”‚        β”‚β”€β”€β”€πŸ“‚screens
 β”‚       β”‚        β”‚   └──user_list_screen.dart
 β”‚       β”‚        β””β”€β”€β”€πŸ“‚widgets
 β”‚       β”‚            └──status_container.dart
 β”‚       β”‚
 β”‚       β”‚β”€β”€β”€πŸ“‚todo
 β”‚       β”‚    β”‚β”€β”€β”€πŸ“‚data
 β”‚       β”‚    β”‚   β”‚β”€β”€πŸ“‚datasources
 β”‚       β”‚    β”‚   β”‚  └──todo_remote_data_source.dart
 β”‚       β”‚    β”‚   β”‚β”€β”€πŸ“‚models
 β”‚       β”‚    β”‚   β”‚   │──todo.dart
 β”‚       β”‚    β”‚   β”‚   └──todo.g.dart
 β”‚       β”‚    β”‚   β””β”€β”€πŸ“‚repositories
 β”‚       β”‚    β”‚       └──todo_repository_impl.dart
 β”‚       β”‚    β”‚β”€β”€β”€πŸ“‚domain
 β”‚       β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚entities
 β”‚       β”‚    β”‚   β”‚   └──todo_entity.dart
 β”‚       β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚repositories
 β”‚       β”‚    β”‚   β”‚   └──todo_repository.dart
 β”‚       β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚usecases
 β”‚       β”‚    β”‚   β”‚   │──create_todo_usecase.dart
 β”‚       β”‚    β”‚   β”‚   │──delete_todo_usecase.dart
 β”‚       β”‚    β”‚   β”‚   │──get_todos_usecase.dart
 β”‚       β”‚    β”‚   β”‚   └──update_todo_usecase.dart
 β”‚       β”‚    └── πŸ“‚presentation
 β”‚       β”‚        β”‚β”€β”€β”€πŸ“‚controller
 β”‚       β”‚        β”‚   └──todo_controller.dart
 β”‚       β”‚        β”‚β”€β”€β”€πŸ“‚screens
 β”‚       β”‚        β”‚   └──todo_list_screen.dart
 β”‚       β”‚        β””β”€β”€β”€πŸ“‚widgets
 β”‚       β”‚            │──circle_container.dart
 β”‚       β”‚            └──todo_list_item.dart
 β”‚       β”‚β”€β”€β”€πŸ“‚post
 β”‚       β”‚    β”‚β”€β”€β”€πŸ“‚data
 β”‚       β”‚    β”‚   β”‚β”€β”€πŸ“‚datasources
 β”‚       β”‚    β”‚   β”‚  └──post_remote_data_source.dart
 β”‚       β”‚    β”‚   β”‚β”€β”€πŸ“‚models
 β”‚       β”‚    β”‚   β”‚   │──post.dart
 β”‚       β”‚    β”‚   β”‚   └──post.g.dart
 β”‚       β”‚    β”‚   β””β”€β”€πŸ“‚repositories
 β”‚       β”‚    β”‚       └──post_repository_impl.dart
 β”‚       β”‚    β”‚β”€β”€β”€πŸ“‚domain
 β”‚       β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚entities
 β”‚       β”‚    β”‚   β”‚   └──post_entity.dart
 β”‚       β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚repositories
 β”‚       β”‚    β”‚   β”‚   └──post_repository.dart
 β”‚       β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚usecases
 β”‚       β”‚    β”‚   β”‚   │──create_post_usecase.dart
 β”‚       β”‚    β”‚   β”‚   │──delete_post_usecase.dart
 β”‚       β”‚    β”‚   β”‚   │──get_posts_usecase.dart
 β”‚       β”‚    β”‚   β”‚   └──update_post_usecase.dart
 β”‚       β”‚    └── πŸ“‚presentation
 β”‚       β”‚        β”‚β”€β”€β”€πŸ“‚controller
 β”‚       β”‚        β”‚   └──post_controller.dart
 β”‚       β”‚        β””β”€β”€β”€πŸ“‚screens
 β”‚       β”‚            │──create_post_screen.dart
 β”‚       β”‚            │──post_detail_screen.dart
 β”‚       β”‚            └──post_list_screen.dart
 β”‚       β””β”€β”€β”€πŸ“‚comment
 β”‚            β”‚β”€β”€β”€πŸ“‚data
 β”‚            β”‚   β”‚β”€β”€πŸ“‚datasources
 β”‚            β”‚   β”‚  └──comment_remote_data_source.dart
 β”‚            β”‚   β”‚β”€β”€πŸ“‚models
 β”‚            β”‚   β”‚   │──comment.dart
 β”‚            β”‚   β”‚   └──comment.g.dart
 β”‚            β”‚   β””β”€β”€πŸ“‚repositories
 β”‚            β”‚       └──comment_repository_impl.dart
 β”‚            β”‚β”€β”€β”€πŸ“‚domain
 β”‚            β”‚   β”‚β”€β”€β”€πŸ“‚entities
 β”‚            β”‚   β”‚   └──comment_entity.dart
 β”‚            β”‚   β”‚β”€β”€β”€πŸ“‚repositories
 β”‚            β”‚   β”‚   └──comment_repository.dart
 β”‚            β”‚   β”‚β”€β”€β”€πŸ“‚usecases
 β”‚            β”‚   β”‚   │──create_comment_usecase.dart
 β”‚            β”‚   β”‚   │──delete_comment_usecase.dart
 β”‚            β”‚   β”‚   └──get_comments_usecase.dart
 β”‚            └── πŸ“‚presentation
 β”‚                β””β”€β”€β”€πŸ“‚controller
 β”‚                    └──comment_controller.dart
 β”‚
 β”‚
 β”‚
 └── πŸ“‚test
     β”‚β”€β”€πŸ“‚test_utils
     β”‚   └─── πŸ“‚data
     β”‚        └───test_data.dart
     β”‚β”€β”€πŸ“‚common
     β”‚   │─── πŸ“‚network
     β”‚   β”‚    └───dio_exception_test.dart
     β”‚   └─── πŸ“‚repository
     β”‚        └───repository_helper_test.dart
     β”‚β”€β”€πŸ“‚core
     β”‚   └───app_extension_test.dart
     β”‚   
     β””β”€β”€πŸ“‚features
         β”‚β”€β”€β”€πŸ“‚user
         β”‚    β”‚β”€β”€β”€πŸ“‚data
         β”‚    β”‚   β”‚β”€β”€πŸ“‚datasources
         β”‚    β”‚   β”‚  │──user_remote_data_source_test.dart
         β”‚    β”‚   β”‚  └──user_remote_data_source_test.mocks.dart
         β”‚    β”‚   β””β”€β”€πŸ“‚repositories
         β”‚    β”‚       │──user_repository_impl_test.dart
         β”‚    β”‚       └──user_repository_impl_test.mocks.dart
         β”‚    β”‚β”€β”€β”€πŸ“‚domain
         β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚usecases
         β”‚    β”‚   β”‚   │──create_user_usecase_test.dart
         β”‚    β”‚   β”‚   │──create_user_usecase_test.mocks.dart
         β”‚    β”‚   β”‚   │──delete_user_usecase_test.dart
         β”‚    β”‚   β”‚   │──get_users_usecase_test.dart
         β”‚    β”‚   β”‚   └──update_user_usecase_test.dart
         β”‚    └── πŸ“‚presentation
         β”‚        β””β”€β”€β”€πŸ“‚controller
         β”‚            └──user_controller_test.dart
         β”‚            └──user_controller_test.mocks.dart
         β”‚
         β”‚β”€β”€β”€πŸ“‚todo
         β”‚    β”‚β”€β”€β”€πŸ“‚data
         β”‚    β”‚   β”‚β”€β”€πŸ“‚datasources
         β”‚    β”‚   β”‚  │──todo_remote_data_source_test.dart
         β”‚    β”‚   β”‚  └──todo_remote_data_source_test.mocks.dart
         β”‚    β”‚   β””β”€β”€πŸ“‚repositories
         β”‚    β”‚       │──todo_repository_impl_test.dart
         β”‚    β”‚       └──todo_repository_impl_test.mocks.dart
         β”‚    β”‚β”€β”€β”€πŸ“‚domain
         β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚usecases
         β”‚    β”‚   β”‚   │──create_todo_usecase_test.dart
         β”‚    β”‚   β”‚   │──create_todo_usecase_test.mocks.dart
         β”‚    β”‚   β”‚   │──delete_todo_usecase_test.dart
         β”‚    β”‚   β”‚   │──get_todos_usecase_test.dart
         β”‚    β”‚   β”‚   └──update_todo_usecase_test.dart
         β”‚    └── πŸ“‚presentation
         β”‚        β””β”€β”€β”€πŸ“‚controller
         β”‚            │──todo_controller_test.dart
         β”‚            └──todo_controller_test.mocks.dart
         β”‚β”€β”€β”€πŸ“‚post
         β”‚    β”‚β”€β”€β”€πŸ“‚data
         β”‚    β”‚   β”‚β”€β”€πŸ“‚datasources
         β”‚    β”‚   β”‚  │──post_remote_data_source_test.dart
         β”‚    β”‚   β”‚  └──post_remote_data_source_test.mocks.dart
         β”‚    β”‚   β””β”€β”€πŸ“‚repositories
         β”‚    β”‚       │──post_repository_impl_test.dart
         β”‚    β”‚       └──post_repository_impl_test.mocks.dart
         β”‚    β”‚β”€β”€β”€πŸ“‚domain
         β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚usecases
         β”‚    β”‚   β”‚   │──create_post_usecase_test.dart
         β”‚    β”‚   β”‚   │──create_post_usecase_test.mocks.dart
         β”‚    β”‚   β”‚   │──delete_post_usecase_test.dart
         β”‚    β”‚   β”‚   │──get_posts_usecase_test.dart
         β”‚    β”‚   β”‚   └──update_post_usecase_test.dart
         β”‚    └── πŸ“‚presentation
         β”‚        β””β”€β”€β”€πŸ“‚controller
         β”‚            │──post_controller_test.dart
         β”‚            └──post_controller_test.mocks.dart
         β””β”€β”€β”€πŸ“‚comment
              β”‚β”€β”€β”€πŸ“‚data
              β”‚   β”‚β”€β”€πŸ“‚datasources
              β”‚   β”‚  │──comment_remote_data_source_test.dart
              β”‚   β”‚  └──comment_remote_data_source_test.mocks.dart
              β”‚   β””β”€β”€πŸ“‚repositories
              β”‚       │──comment_repository_impl_test.dart
              β”‚       └──comment_repository_impl_test.mocks.dart
              β”‚β”€β”€β”€πŸ“‚domain
              β”‚   β”‚β”€β”€β”€πŸ“‚usecases
              β”‚   β”‚   │──create_comment_usecase_test.dart
              β”‚   β”‚   │──create_comment_usecase.mocks.dart
              β”‚   β”‚   │──delete_comment_usecase_test.dart
              β”‚   β”‚   └──get_comments_usecase_test.dart
              └── πŸ“‚presentation
                  β””β”€β”€β”€πŸ“‚controller
                      │──comment_controller_test.dart
                      └──comment_controller_test.mocks.dart



πŸ“‚ Directory Structure (MVVM architecture version + Bloc)

πŸ“‚lib
│───main.dart  
│───di.dart  
β”‚β”€β”€β”€πŸ“‚common  
β”‚   β”‚β”€β”€β”€πŸ“‚bloc
β”‚   β”‚   │──bloc_helper.dart
β”‚   β”‚   └──generic_bloc_state.dart
β”‚   β”‚β”€β”€β”€πŸ“‚repository
β”‚   β”‚   └──repository_helper.dart
β”‚   β”‚β”€β”€β”€πŸ“‚network
β”‚   β”‚   │──api_helper.dart
β”‚   β”‚   │──api_result.dart
β”‚   β”‚   │──api_result.freezed.dart
β”‚   β”‚   │──dio_client.dart
β”‚   β”‚   │──dio_exception.dart
β”‚   β”‚   └──dio_interceptor.dart
β”‚   β”‚β”€β”€β”€πŸ“‚widget
β”‚   β”‚   │──date_time_picker.dart
β”‚   β”‚   │──drop_down.dart
β”‚   β”‚   │──empty_widget.dart
β”‚   β”‚   │──popup_menu.dart
β”‚   β”‚   │──spinkit_indicator.dart
β”‚   β”‚   └──text_input.dart
β”‚   β””β”€β”€β”€πŸ“‚dialog
β”‚       │──create_dialog.dart
β”‚       │──delete_dialog.dart
β”‚       │──progress_dialog.dart
β”‚       └──retry_dialog.dart
β”‚β”€β”€β”€πŸ“‚core
β”‚   │──api_config.dart
β”‚   │──app_asset.dart
β”‚   │──app_extension.dart
β”‚   │──app_string.dart
β”‚   │──app_style.dart
β”‚   └──app_theme.dart
β”‚
β”‚β”€β”€β”€πŸ“‚data
β”‚   β”‚β”€β”€β”€πŸ“‚api
β”‚   β”‚    β”‚β”€β”€β”€πŸ“‚comment
β”‚   β”‚    β”‚   └──comment_api.dart
β”‚   β”‚    β”‚β”€β”€β”€πŸ“‚post
β”‚   β”‚    β”‚   └──post_api.dart
β”‚   β”‚    β”‚β”€β”€β”€πŸ“‚todo
β”‚   β”‚    β”‚   └──todo_api.dart
β”‚   β”‚    β””β”€β”€β”€πŸ“‚user
β”‚   β”‚        └──user_api.dart
β”‚   β”‚    
β”‚   β””β”€β”€β”€πŸ“‚model 
β”‚        β”‚β”€β”€β”€πŸ“‚comment
β”‚        β”‚   │──comment.dart
β”‚        β”‚   └──comment.g.dart
β”‚        β”‚β”€β”€β”€πŸ“‚post
β”‚        β”‚   │──post.dart
β”‚        β”‚   └──post.g.dart
β”‚        β”‚β”€β”€β”€πŸ“‚todo
β”‚        β”‚   │──todo.dart
β”‚        β”‚   └──todo.g.dart
β”‚        β””β”€β”€β”€πŸ“‚user
β”‚            │──user.dart
β”‚            └──user.g.dart 
β”‚    
β”‚β”€β”€β”€πŸ“‚repository
β”‚    β”‚β”€β”€β”€πŸ“‚comment
β”‚    β”‚   └──comment_repository.dart
β”‚    β”‚β”€β”€β”€πŸ“‚post
β”‚    β”‚   └──post_repository.dart
β”‚    β”‚β”€β”€β”€πŸ“‚todo
β”‚    β”‚   └──todo_repository.dart
β”‚    β””β”€β”€β”€πŸ“‚user
β”‚        └──user_repository.dart
β”‚
β”‚β”€β”€β”€πŸ“‚view
β”‚    β”‚β”€β”€β”€πŸ“‚post
β”‚    β”‚   β””β”€β”€πŸ“‚screen
β”‚    β”‚      │──create_post_screen.dart
β”‚    β”‚      │──post_detail_screen.dart
β”‚    β”‚      └──post_list_screen.dart
β”‚    β”‚    
β”‚    β”‚β”€β”€β”€πŸ“‚todo
β”‚    β”‚   β”‚β”€β”€πŸ“‚screen
β”‚    β”‚   β”‚  └──todo_list_screen.dart
β”‚    β”‚   β””β”€β”€πŸ“‚widget
β”‚    β”‚      │──circle_container.dart
β”‚    β”‚      └──todo_list_item.dart
β”‚    β”‚
β”‚    β””β”€β”€β”€πŸ“‚user
β”‚        β”‚β”€β”€πŸ“‚screen
β”‚        β”‚  └──user_list_screen.dart
β”‚        β””β”€β”€πŸ“‚widget
β”‚           └──status_container.dart
β”‚     
β””β”€β”€β”€πŸ“‚viewmodel
         β”‚β”€β”€β”€πŸ“‚comment
         β”‚   β””β”€β”€πŸ“‚bloc
         β”‚      └──comment_bloc.dart
         β”‚      └──comment_event.dart
         β”‚β”€β”€β”€πŸ“‚post
         β”‚   β””β”€β”€πŸ“‚bloc
         β”‚      └──post_bloc.dart
         β”‚      └──post_event.dart
         β”‚β”€β”€β”€πŸ“‚todo
         β”‚   β””β”€β”€πŸ“‚bloc
         β”‚      │──todo_bloc.dart
         β”‚      └──todo_event.dart
         β””β”€β”€β”€πŸ“‚user
             β””β”€β”€πŸ“‚bloc
                │──user_bloc.dart
                └──user_event.dart




πŸ“‚ Directory Structure (MVVM architecture version + Cubit)

πŸ“‚lib
│───main.dart  
│───di.dart  
β”‚β”€β”€β”€πŸ“‚common  
β”‚   β”‚β”€β”€β”€πŸ“‚cubit
β”‚   β”‚   │──generic_cubit.dart
β”‚   β”‚   └──generic_cubit_state.dart
β”‚   β”‚β”€β”€β”€πŸ“‚repository
β”‚   β”‚   └──repository_helper.dart
β”‚   β”‚β”€β”€β”€πŸ“‚network
β”‚   β”‚   │──api_helper.dart
β”‚   β”‚   │──api_result.dart
β”‚   β”‚   │──api_result.freezed.dart
β”‚   β”‚   │──dio_client.dart
β”‚   β”‚   │──dio_exception.dart
β”‚   β”‚   └──dio_interceptor.dart
β”‚   β”‚β”€β”€β”€πŸ“‚widget
β”‚   β”‚   │──date_time_picker.dart
β”‚   β”‚   │──drop_down.dart
β”‚   β”‚   │──empty_widget.dart
β”‚   β”‚   │──popup_menu.dart
β”‚   β”‚   │──spinkit_indicator.dart
β”‚   β”‚   └──text_input.dart
β”‚   β””β”€β”€β”€πŸ“‚dialog
β”‚       │──create_dialog.dart
β”‚       │──delete_dialog.dart
β”‚       │──progress_dialog.dart
β”‚       └──retry_dialog.dart
β”‚β”€β”€β”€πŸ“‚core
β”‚   │──api_config.dart
β”‚   │──app_asset.dart
β”‚   │──app_extension.dart
β”‚   │──app_string.dart
β”‚   │──app_style.dart
β”‚   └──app_theme.dart
β”‚
β”‚β”€β”€β”€πŸ“‚data
β”‚   β”‚β”€β”€β”€πŸ“‚api
β”‚   β”‚    β”‚β”€β”€β”€πŸ“‚comment
β”‚   β”‚    β”‚   └──comment_api.dart
β”‚   β”‚    β”‚β”€β”€β”€πŸ“‚post
β”‚   β”‚    β”‚   └──post_api.dart
β”‚   β”‚    β”‚β”€β”€β”€πŸ“‚todo
β”‚   β”‚    β”‚   └──todo_api.dart
β”‚   β”‚    β””β”€β”€β”€πŸ“‚user
β”‚   β”‚        └──user_api.dart
β”‚   β”‚    
β”‚   β””β”€β”€β”€πŸ“‚model 
β”‚        β”‚β”€β”€β”€πŸ“‚comment
β”‚        β”‚   │──comment.dart
β”‚        β”‚   └──comment.g.dart
β”‚        β”‚β”€β”€β”€πŸ“‚post
β”‚        β”‚   │──post.dart
β”‚        β”‚   └──post.g.dart
β”‚        β”‚β”€β”€β”€πŸ“‚todo
β”‚        β”‚   │──todo.dart
β”‚        β”‚   └──todo.g.dart
β”‚        β””β”€β”€β”€πŸ“‚user
β”‚            │──user.dart
β”‚            └──user.g.dart 
β”‚    
β”‚β”€β”€β”€πŸ“‚repository
β”‚    β”‚β”€β”€β”€πŸ“‚comment
β”‚    β”‚   └──comment_repository.dart
β”‚    β”‚β”€β”€β”€πŸ“‚post
β”‚    β”‚   └──post_repository.dart
β”‚    β”‚β”€β”€β”€πŸ“‚todo
β”‚    β”‚   └──todo_repository.dart
β”‚    β””β”€β”€β”€πŸ“‚user
β”‚        └──user_repository.dart
β”‚
β”‚β”€β”€β”€πŸ“‚view
β”‚    β”‚β”€β”€β”€πŸ“‚post
β”‚    β”‚   β””β”€β”€πŸ“‚screen
β”‚    β”‚      │──create_post_screen.dart
β”‚    β”‚      │──post_detail_screen.dart
β”‚    β”‚      └──post_list_screen.dart
β”‚    β”‚    
β”‚    β”‚β”€β”€β”€πŸ“‚todo
β”‚    β”‚   β”‚β”€β”€πŸ“‚screen
β”‚    β”‚   β”‚  └──todo_list_screen.dart
β”‚    β”‚   β””β”€β”€πŸ“‚widget
β”‚    β”‚      │──circle_container.dart
β”‚    β”‚      └──todo_list_item.dart
β”‚    β”‚
β”‚    β””β”€β”€β”€πŸ“‚user
β”‚        β”‚β”€β”€πŸ“‚screen
β”‚        β”‚  └──user_list_screen.dart
β”‚        β””β”€β”€πŸ“‚widget
β”‚           └──status_container.dart
β”‚     
β””β”€β”€β”€πŸ“‚viewmodel
         β”‚β”€β”€β”€πŸ“‚comment
         β”‚   β””β”€β”€πŸ“‚cubit
         β”‚      └──comment_cubit.dart
         β”‚β”€β”€β”€πŸ“‚post
         β”‚   β””β”€β”€πŸ“‚cubit
         β”‚      └──post_cubit.dart
         β”‚β”€β”€β”€πŸ“‚todo
         β”‚   β””β”€β”€πŸ“‚cubit
         β”‚      └──todo_cubit.dart
         β””β”€β”€β”€πŸ“‚user
             β””β”€β”€πŸ“‚cubit
                └──user_cubit.dart




πŸ“‚ Directory Structure (MVVM architecture version + GetX)

πŸ“‚lib
│───main.dart  
│───di.dart  
β”‚β”€β”€β”€πŸ“‚common  
β”‚   β”‚β”€β”€β”€πŸ“‚controller
β”‚   β”‚   └──base_controller.dart
β”‚   β”‚β”€β”€β”€πŸ“‚repository
β”‚   β”‚   └──repository_helper.dart
β”‚   β”‚β”€β”€β”€πŸ“‚network
β”‚   β”‚   │──api_helper.dart
β”‚   β”‚   │──api_result.dart
β”‚   β”‚   │──api_result.freezed.dart
β”‚   β”‚   │──dio_client.dart
β”‚   β”‚   │──dio_exception.dart
β”‚   β”‚   └──dio_interceptor.dart
β”‚   β”‚β”€β”€β”€πŸ“‚widget
β”‚   β”‚   │──date_time_picker.dart
β”‚   β”‚   │──drop_down.dart
β”‚   β”‚   │──empty_widget.dart
β”‚   β”‚   │──popup_menu.dart
β”‚   β”‚   │──spinkit_indicator.dart
β”‚   β”‚   └──text_input.dart
β”‚   β””β”€β”€β”€πŸ“‚dialog
β”‚       │──create_dialog.dart
β”‚       │──delete_dialog.dart
β”‚       │──progress_dialog.dart
β”‚       └──retry_dialog.dart
β”‚β”€β”€β”€πŸ“‚core
β”‚   │──api_config.dart
β”‚   │──app_asset.dart
β”‚   │──app_extension.dart
β”‚   │──app_string.dart
β”‚   │──app_style.dart
β”‚   └──app_theme.dart
β”‚
β”‚β”€β”€β”€πŸ“‚data
β”‚   β”‚β”€β”€β”€πŸ“‚api
β”‚   β”‚    β”‚β”€β”€β”€πŸ“‚comment
β”‚   β”‚    β”‚   └──comment_api.dart
β”‚   β”‚    β”‚β”€β”€β”€πŸ“‚post
β”‚   β”‚    β”‚   └──post_api.dart
β”‚   β”‚    β”‚β”€β”€β”€πŸ“‚todo
β”‚   β”‚    β”‚   └──todo_api.dart
β”‚   β”‚    β””β”€β”€β”€πŸ“‚user
β”‚   β”‚        └──user_api.dart
β”‚   β”‚    
β”‚   β””β”€β”€β”€πŸ“‚model 
β”‚        β”‚β”€β”€β”€πŸ“‚comment
β”‚        β”‚   │──comment.dart
β”‚        β”‚   └──comment.g.dart
β”‚        β”‚β”€β”€β”€πŸ“‚post
β”‚        β”‚   │──post.dart
β”‚        β”‚   └──post.g.dart
β”‚        β”‚β”€β”€β”€πŸ“‚todo
β”‚        β”‚   │──todo.dart
β”‚        β”‚   └──todo.g.dart
β”‚        β””β”€β”€β”€πŸ“‚user
β”‚            │──user.dart
β”‚            └──user.g.dart 
β”‚    
β”‚β”€β”€β”€πŸ“‚repository
β”‚    β”‚β”€β”€β”€πŸ“‚comment
β”‚    β”‚   └──comment_repository.dart
β”‚    β”‚β”€β”€β”€πŸ“‚post
β”‚    β”‚   └──post_repository.dart
β”‚    β”‚β”€β”€β”€πŸ“‚todo
β”‚    β”‚   └──todo_repository.dart
β”‚    β””β”€β”€β”€πŸ“‚user
β”‚        └──user_repository.dart
β”‚
β”‚β”€β”€β”€πŸ“‚view
β”‚    β”‚β”€β”€β”€πŸ“‚post
β”‚    β”‚   β””β”€β”€πŸ“‚screen
β”‚    β”‚      │──create_post_screen.dart
β”‚    β”‚      │──post_detail_screen.dart
β”‚    β”‚      └──post_list_screen.dart
β”‚    β”‚    
β”‚    β”‚β”€β”€β”€πŸ“‚todo
β”‚    β”‚   β”‚β”€β”€πŸ“‚screen
β”‚    β”‚   β”‚  └──todo_list_screen.dart
β”‚    β”‚   β””β”€β”€πŸ“‚widget
β”‚    β”‚      │──circle_container.dart
β”‚    β”‚      └──todo_list_item.dart
β”‚    β”‚
β”‚    β””β”€β”€β”€πŸ“‚user
β”‚        β”‚β”€β”€πŸ“‚screen
β”‚        β”‚  └──user_list_screen.dart
β”‚        β””β”€β”€πŸ“‚widget
β”‚           └──status_container.dart
β”‚     
β””β”€β”€β”€πŸ“‚viewmodel
         β”‚β”€β”€β”€πŸ“‚comment
         β”‚   β””β”€β”€πŸ“‚controller
         β”‚      └──comment_controller.dart
         β”‚β”€β”€β”€πŸ“‚post
         β”‚   β””β”€β”€πŸ“‚controller
         β”‚      └──post_controller.dart
         β”‚β”€β”€β”€πŸ“‚todo
         β”‚   β””β”€β”€πŸ“‚controller
         β”‚      └──todo_controller.dart
         β””β”€β”€β”€πŸ“‚user
             β””β”€β”€πŸ“‚controller
                └──user_controller.dart


πŸ“‚ Directory Structure (Simple layered architecture version + Cubit)

πŸ“‚lib
 │───main.dart  
 β”‚β”€β”€β”€πŸ“‚common  
 β”‚   β”‚β”€β”€β”€πŸ“‚cubit
 β”‚   β”‚   │──generic_cubit.dart
 β”‚   β”‚   └──generic_cubit_state.dart
 β”‚   β”‚β”€β”€β”€πŸ“‚network
 β”‚   β”‚   │──api_base.dart
 β”‚   β”‚   │──api_result.dart
 β”‚   β”‚   │──api_result.freezed.dart
 β”‚   β”‚   │──dio_client.dart
 β”‚   β”‚   │──dio_exception.dart
 β”‚   β”‚   └──dio_interceptor.dart
 β”‚   β”‚β”€β”€β”€πŸ“‚widget
 β”‚   β”‚   │──date_time_picker.dart
 β”‚   β”‚   │──drop_down.dart
 β”‚   β”‚   │──empty_widget.dart
 β”‚   β”‚   │──popup_menu.dart
 β”‚   β”‚   │──spinkit_indicator.dart
 β”‚   β”‚   └──text_input.dart 
 β”‚   β””β”€β”€β”€πŸ“‚dialog
 β”‚       │──create_dialog.dart
 β”‚       │──delete_dialog.dart
 β”‚       │──progress_dialog.dart
 β”‚       └──retry_dialog.dart
 β”‚β”€β”€β”€πŸ“‚core 
 β”‚   │──api_config.dart
 β”‚   │──app_asset.dart
 β”‚   │──app_extension.dart
 β”‚   │──app_string.dart
 β”‚   │──app_style.dart
 β”‚   └──app_theme.dart
 β””β”€β”€β”€πŸ“‚features
     β”‚β”€β”€β”€πŸ“‚comment
     β”‚    β”‚β”€β”€β”€πŸ“‚cubit
     β”‚    β”‚   └──comment_cubit.dart
     β”‚    β””β”€β”€β”€πŸ“‚data
     β”‚        β”‚β”€β”€β”€πŸ“‚model
     β”‚        β”‚   │──comment.dart
     β”‚        β”‚   └──comment.g.dart
     β”‚        β””β”€β”€β”€πŸ“‚provider
     β”‚            β””β”€β”€πŸ“‚remote
     β”‚               └──comment_api.dart
     β”‚β”€β”€β”€πŸ“‚post
     β”‚    β”‚β”€β”€β”€πŸ“‚cubit
     β”‚    β”‚   └──post_cubit.dart
     β”‚    β”‚β”€β”€β”€πŸ“‚data
     β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚model
     β”‚    β”‚   β”‚   │──post.dart
     β”‚    β”‚   β”‚   └──post.g.dart
     β”‚    β”‚   β””β”€β”€β”€πŸ“‚provider
     β”‚    β”‚       β””β”€β”€πŸ“‚remote
     β”‚    β”‚          └──psot_api.dart
     β”‚    β””β”€β”€β”€πŸ“‚view  
     β”‚        β””β”€β”€πŸ“‚screen
     β”‚           │──create_post_screen.dart
     β”‚           │──post_detail_screen.dart
     β”‚           └──post_list_screen.dart
     β”‚β”€β”€β”€πŸ“‚todo
     β”‚    β”‚β”€β”€β”€πŸ“‚cubit
     β”‚    β”‚   └──todo_cubit.dart
     β”‚    β”‚β”€β”€β”€πŸ“‚data
     β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚model
     β”‚    β”‚   β”‚   │──todo.dart
     β”‚    β”‚   β”‚   └──todo.g.dart
     β”‚    β”‚   β””β”€β”€β”€πŸ“‚provider
     β”‚    β”‚       β””β”€β”€πŸ“‚remote
     β”‚    β”‚          └──todo_api.dart
     β”‚    β””β”€β”€β”€πŸ“‚view  
     β”‚        β”‚β”€β”€πŸ“‚screen
     β”‚        β”‚  └──todo_list_screen.dart
     β”‚        β””β”€β”€πŸ“‚widget
     β”‚            │──circle_container.dart
     β”‚            └──todo_list_item.dart
     β””β”€β”€β”€πŸ“‚user
          β”‚β”€β”€β”€πŸ“‚cubit
          β”‚   └──user_cubit.dart
          β”‚β”€β”€β”€πŸ“‚data
          β”‚   β”‚β”€β”€β”€πŸ“‚model
          β”‚   β”‚   │──user.dart
          β”‚   β”‚   └──user.g.dart
          β”‚   β””β”€β”€β”€πŸ“‚provider
          β”‚       β””β”€β”€πŸ“‚remote
          β”‚          └──user_api.dart
          β””β”€β”€β”€πŸ“‚view  
              β”‚β”€β”€πŸ“‚screen
              β”‚  └──user_list_screen.dart
              β””β”€β”€πŸ“‚widget
                 └──status_container.dart

πŸ“‚ Directory Structure (Simple layered architecture version + Bloc)

πŸ“‚lib
 │───main.dart  
 β”‚β”€β”€β”€πŸ“‚common  
 β”‚   β”‚β”€β”€β”€πŸ“‚bloc
 β”‚   β”‚   │──bloc_helper.dart
 β”‚   β”‚   └──generic_bloc_state.dart
 β”‚   β”‚β”€β”€β”€πŸ“‚network
 β”‚   β”‚   │──api_base.dart
 β”‚   β”‚   │──api_result.dart
 β”‚   β”‚   │──api_result.freezed.dart
 β”‚   β”‚   │──dio_client.dart
 β”‚   β”‚   │──dio_exception.dart
 β”‚   β”‚   └──dio_interceptor.dart
 β”‚   β”‚β”€β”€β”€πŸ“‚widget
 β”‚   β”‚   │──date_time_picker.dart
 β”‚   β”‚   │──drop_down.dart
 β”‚   β”‚   │──empty_widget.dart
 β”‚   β”‚   │──popup_menu.dart
 β”‚   β”‚   │──spinkit_indicator.dart
 β”‚   β”‚   └──text_input.dart 
 β”‚   β””β”€β”€β”€πŸ“‚dialog
 β”‚       │──create_dialog.dart
 β”‚       │──delete_dialog.dart
 β”‚       │──progress_dialog.dart
 β”‚       └──retry_dialog.dart
 β”‚β”€β”€β”€πŸ“‚core 
 β”‚   │──api_config.dart
 β”‚   │──app_asset.dart
 β”‚   │──app_extension.dart
 β”‚   │──app_string.dart
 β”‚   │──app_style.dart
 β”‚   └──app_theme.dart
 β””β”€β”€β”€πŸ“‚features
     β”‚β”€β”€β”€πŸ“‚comment
     β”‚    β”‚β”€β”€β”€πŸ“‚bloc
     β”‚    β”‚   │──comment_bloc.dart
     β”‚    β”‚   └──comment_event.dart
     β”‚    β””β”€β”€β”€πŸ“‚data
     β”‚        β”‚β”€β”€β”€πŸ“‚model
     β”‚        β”‚   │──comment.dart
     β”‚        β”‚   └──comment.g.dart
     β”‚        β””β”€β”€β”€πŸ“‚provider
     β”‚            β””β”€β”€πŸ“‚remote
     β”‚               └──comment_api.dart
     β”‚β”€β”€β”€πŸ“‚post
     β”‚    β”‚β”€β”€β”€πŸ“‚bloc
     β”‚    β”‚   └──post_bloc.dart
     β”‚    β”‚   │──post_event.dart
     β”‚    β”‚β”€β”€β”€πŸ“‚data
     β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚model
     β”‚    β”‚   β”‚   │──post.dart
     β”‚    β”‚   β”‚   └──post.g.dart
     β”‚    β”‚   β””β”€β”€β”€πŸ“‚provider
     β”‚    β”‚       β””β”€β”€πŸ“‚remote
     β”‚    β”‚          └──psot_api.dart
     β”‚    β””β”€β”€β”€πŸ“‚view  
     β”‚        β””β”€β”€πŸ“‚screen
     β”‚           │──create_post_screen.dart
     β”‚           │──post_detail_screen.dart
     β”‚           └──post_list_screen.dart
     β”‚β”€β”€β”€πŸ“‚todo
     β”‚    β”‚β”€β”€β”€πŸ“‚bloc
     β”‚    β”‚   │──todo_bloc.dart
     β”‚    β”‚   └──todo_event.dart
     β”‚    β”‚β”€β”€β”€πŸ“‚data
     β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚model
     β”‚    β”‚   β”‚   │──todo.dart
     β”‚    β”‚   β”‚   └──todo.g.dart
     β”‚    β”‚   β””β”€β”€β”€πŸ“‚provider
     β”‚    β”‚       β””β”€β”€πŸ“‚remote
     β”‚    β”‚          └──todo_api.dart
     β”‚    β””β”€β”€β”€πŸ“‚view  
     β”‚        β”‚β”€β”€πŸ“‚screen
     β”‚        β”‚  └──todo_list_screen.dart
     β”‚        β””β”€β”€πŸ“‚widget
     β”‚            │──circle_container.dart
     β”‚            └──todo_list_item.dart
     β””β”€β”€β”€πŸ“‚user
          β”‚β”€β”€β”€πŸ“‚bloc
          β”‚   │──user_bloc.dart
          β”‚   └──user_event.dart
          β”‚β”€β”€β”€πŸ“‚data
          β”‚   β”‚β”€β”€β”€πŸ“‚model
          β”‚   β”‚   │──user.dart
          β”‚   β”‚   └──user.g.dart
          β”‚   β””β”€β”€β”€πŸ“‚provider
          β”‚       β””β”€β”€πŸ“‚remote
          β”‚          └──user_api.dart
          β””β”€β”€β”€πŸ“‚view  
              β”‚β”€β”€πŸ“‚screen
              β”‚  └──user_list_screen.dart
              β””β”€β”€πŸ“‚widget
                 └──status_container.dart

πŸ“‚ Directory Structure (Simple layered architecture version + GetX)

πŸ“‚lib
 │───main.dart  
 β”‚β”€β”€β”€πŸ“‚common  
 β”‚   β”‚β”€β”€β”€πŸ“‚controller
 β”‚   β”‚   └──base_controller.dart
 β”‚   β”‚β”€β”€β”€πŸ“‚network
 β”‚   β”‚   │──api_base.dart
 β”‚   β”‚   │──dio_client.dart
 β”‚   β”‚   │──dio_exception.dart
 β”‚   β”‚   └──dio_interceptor.dart
 β”‚   β”‚β”€β”€β”€πŸ“‚widget
 β”‚   β”‚   │──async_widget.dart
 β”‚   β”‚   │──date_time_picker.dart
 β”‚   β”‚   │──drop_down.dart
 β”‚   β”‚   │──empty_widget.dart
 β”‚   β”‚   │──popup_menu.dart
 β”‚   β”‚   │──spinkit_indicator.dart
 β”‚   β”‚   └──text_input.dart 
 β”‚   β””β”€β”€β”€πŸ“‚dialog
 β”‚       │──create_dialog.dart
 β”‚       │──delete_dialog.dart
 β”‚       │──progress_dialog.dart
 β”‚       └──retry_dialog.dart
 β”‚β”€β”€β”€πŸ“‚core 
 β”‚   │──api_config.dart
 β”‚   │──app_asset.dart
 β”‚   │──app_extension.dart
 β”‚   │──app_string.dart
 β”‚   │──app_style.dart
 β”‚   └──app_theme.dart
 β””β”€β”€β”€πŸ“‚features
     β”‚β”€β”€β”€πŸ“‚comment
     β”‚    β”‚β”€β”€β”€πŸ“‚controller
     β”‚    β”‚   └──comment_controller.dart
     β”‚    β””β”€β”€β”€πŸ“‚data
     β”‚        β”‚β”€β”€β”€πŸ“‚model
     β”‚        β”‚   │──comment.dart
     β”‚        β”‚   └──comment.g.dart
     β”‚        β””β”€β”€β”€πŸ“‚provider
     β”‚            β””β”€β”€πŸ“‚remote
     β”‚               └──comment_api.dart
     β”‚β”€β”€β”€πŸ“‚post
     β”‚    β”‚β”€β”€β”€πŸ“‚controller
     β”‚    β”‚   └──post_controller.dart
     β”‚    β”‚β”€β”€β”€πŸ“‚data
     β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚model
     β”‚    β”‚   β”‚   │──post.dart
     β”‚    β”‚   β”‚   └──post.g.dart
     β”‚    β”‚   β””β”€β”€β”€πŸ“‚provider
     β”‚    β”‚       β””β”€β”€πŸ“‚remote
     β”‚    β”‚          └──psot_api.dart
     β”‚    β””β”€β”€β”€πŸ“‚view  
     β”‚        β””β”€β”€πŸ“‚screen
     β”‚           │──create_post_screen.dart
     β”‚           │──post_detail_screen.dart
     β”‚           └──post_list_screen.dart
     β”‚β”€β”€β”€πŸ“‚todo
     β”‚    β”‚β”€β”€β”€πŸ“‚controller
     β”‚    β”‚   └──todo_controller.dart
     β”‚    β”‚β”€β”€β”€πŸ“‚data
     β”‚    β”‚   β”‚β”€β”€β”€πŸ“‚model
     β”‚    β”‚   β”‚   │──todo.dart
     β”‚    β”‚   β”‚   └──todo.g.dart
     β”‚    β”‚   β””β”€β”€β”€πŸ“‚provider
     β”‚    β”‚       β””β”€β”€πŸ“‚remote
     β”‚    β”‚          └──todo_api.dart
     β”‚    β””β”€β”€β”€πŸ“‚view  
     β”‚        β”‚β”€β”€πŸ“‚screen
     β”‚        β”‚  └──todo_list_screen.dart
     β”‚        β””β”€β”€πŸ“‚widget
     β”‚            │──circle_container.dart
     β”‚            └──todo_list_item.dart
     β””β”€β”€β”€πŸ“‚user
          β”‚β”€β”€β”€πŸ“‚controller
          β”‚   └──user_controller.dart
          β”‚β”€β”€β”€πŸ“‚data
          β”‚   β”‚β”€β”€β”€πŸ“‚model
          β”‚   β”‚   │──user.dart
          β”‚   β”‚   └──user.g.dart
          β”‚   β””β”€β”€β”€πŸ“‚provider
          β”‚       β””β”€β”€πŸ“‚remote
          β”‚          └──user_api.dart
          β””β”€β”€β”€πŸ“‚view  
              β”‚β”€β”€πŸ“‚screen
              β”‚  └──user_list_screen.dart
              β””β”€β”€πŸ“‚widget
                 └──status_container.dart



🎯 Other flutter projects

Project Name Stars
Japanese restaurant app GitHub stars
Office furniture store app GitHub stars
Ecommerce app GitHub stars

About

πŸš€ User management app built in flutter using clean architecture, MVVM, get it, dio, RxDart, bloc, cubit, getX and provider + Unit Testing

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published