How to Structure Your Flutter App Like a Pro (with Riverpod, REST, and Clean Architecture)

Organizing your Flutter project folder structure is crucial for scalability, teamwork, and maintenance, especially as your app grows.

I’ll walk you through a clean, modular, and scalable folder structure used by professional Flutter developers, with real-world use cases and tips — especially good if you’re planning to use state management (e.g., Provider, Riverpod), REST APIs, and clean architecture principles.


✅ Recommended Folder Structure (Best Practice)

lib/
│
├── core/                👈 App-wide constants, utilities, themes
│   ├── constants/
│   ├── exceptions/
│   ├── themes/
│   └── utils/
│
├── features/            👈 Feature-based modules (recommended)
│   ├── auth/
│   │   ├── data/        🔹 API calls, local storage
│   │   ├── domain/      🔹 Models & business logic
│   │   ├── presentation/🔹 UI: screens, widgets
│   │   └── providers/   🔹 Riverpod or Provider files
│   │
│   ├── home/
│   ├── profile/
│   └── ...
│
├── shared/              👈 Reusable widgets across the app
│   ├── widgets/
│   └── dialogs/
│
├── services/            👈 External services (Dio, Supabase, Firebase)
│   ├── network/
│   ├── local_storage/
│   └── notification/
│
├── main.dart            👈 Entry point
├── router.dart          👈 App navigation
└── app.dart             👈 App widget & setup

📦 Folder Purpose Explained

1. core/ — Application-wide tools

  • Global constants: colors.dart, app_strings.dart
  • Theme files
  • Utility functions
  • Custom error classes or logger helpers
Text(AppStrings.welcome)

2. features/ — Per-feature organization (Recommended ✅)

Each feature (like auth, chat, home, profile) is isolated, making it easier to work in teams and test.

Inside each feature:

SubfolderContents
data/APIs, services, data sources
domain/Models, use cases, business logic
presentation/Screens, widgets, UI logic
providers/Riverpod, Provider, or BLoC files

🔁 This aligns with Clean Architecture.


3. shared/ — Reusable components

  • Buttons, dialogs, custom widgets
  • Shared styles and components
import 'package:your_app/shared/widgets/custom_button.dart';

4. services/ — External integrations

  • Dio API handler
  • Supabase / Firebase
  • Shared preferences
  • Notification handlers

You can structure it as:

services/
├── dio_service.dart
├── supabase_service.dart
└── local_storage_service.dart

5. main.dart, router.dart, app.dart

  • main.dart: App entry point
  • app.dart: Top-level MaterialApp, providers
  • router.dart: Define named routes or GoRouter setup

🚧 Example of a Feature Module: auth/

features/
└── auth/
    ├── data/
    │   └── auth_remote_data_source.dart
    ├── domain/
    │   ├── user_model.dart
    │   └── auth_use_case.dart
    ├── presentation/
    │   ├── login_screen.dart
    │   └── signup_screen.dart
    └── providers/
        └── auth_provider.dart

🧠 Real-World Analogy

Think of it like a supermarket with sections:

  • core/ = the store’s electricity and lights (global settings)
  • features/ = separate aisles (fruits, meat, bakery…)
  • shared/ = shelves and baskets used in every aisle
  • services/ = delivery truck that brings goods (API, local DB)

🛠 Tools to Make It Easier

ToolPurpose
very_good_cliGenerates structured Flutter project
flutter_modularHelps structure feature modules
riverpodWorks beautifully with this structure

✅ Summary

GoalWhy This Structure Helps
ScalabilityEasy to add features like cart, orders, notifications
Clean CodeLogic is separated from UI and data
Team WorkDifferent teams can work in features/* independently
TestingEasier to test domain and data layers

Leave a Reply

Your email address will not be published. Required fields are marked *