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

Repository files navigation

πŸ”₯ 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

  • 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 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.


πŸ§ͺ 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