• Stars
    star
    190
  • Rank 199,646 (Top 4 %)
  • Language
    Dart
  • License
    BSD 2-Clause "Sim...
  • Created over 1 year ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

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

πŸ”₯ Go Rest app

In this project, we are going to build a user management app using Flutter. We have used the Go REST API to make HTTP request methods. This API provides all sorts of methods that we need: GET, POST, PUT, and DELETE. We will call all endpoints (users/todos/posts/comments) provided to us by the Go REST API using the Dio package in our app. We have performed different operations like selecting, adding, editing, and removing users, as well as user posts, todos, and comments.


πŸ–Ό 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


🀝 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 limitation

β€’ The user endpoint contains ten user objects by default. If any of them are deleted, they will be replaced with a new JSON object. This means that the length of the user list will always be ten, and it is not possible to create more than ten user objects. This also applies if you want to add query parameters to the users.

β€’ To use the request methods PUT, POST, PATCH, and DELETE, you need to provide an access token. This token must be passed with the "Authorization" header as a Bearer token. I have already included my own token in the app. However, if you receive an Unauthorized Error (401), please go to this link to obtain a new token and replace the old token in the api_config file located in the core directory.

β€’ Please note that the data is not permanent and will be changed or deleted every 20 minutes to 1 hour.


πŸ—‚ 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 βœ”οΈ βœ”οΈ βœ”οΈ βœ”


πŸ“š 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
β”‚   β”‚β”€β”€β”€πŸ“‚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)

πŸ“‚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




πŸ“‚ 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
 β”‚   β”‚   │──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