# Base Project

This article is **complete** when combined with [Clean Architecture](https://wong-coupon.gitbook.io/flutter/easy-code/flutter-clean-architecture) and [Package](https://chatgpt.com/c/*LINK*).

## **Why Do You Need a Base Project?**

Any Flutter developer, after working on multiple projects, **wants to create a project template** to speed up the initialization of future projects. However, **extracting reusable parts and setting up the project structure from scratch** can be **time-consuming and tedious**.

To solve this, I explored **various ways** to automate the creation of essential files and folders. One approach is **using Windows command-line tools** to generate files, but a **more powerful** tool that can **save time for you and your team** is **Mason**.

If you're unfamiliar with **Mason**, check out my guide:\
[Boost Your Flutter Development Efficiency with Mason](https://mymoneycoupon.web.app/en/doc/help/flutter/boost-your-flutter-development-efficiency-with-mason)

## **Essential Libraries for a Base Project**

Below is a list of **important libraries** that I use to ensure the code is **clean, scalable, and maintainable**.

### **Dependency Injection with `get_it`**

[get\_it on pub.dev](https://pub.dev/packages/get_it)

* Helps with **data retrieval** and **dependency injection**.
* Allows access to repositories **anywhere in the project** without manually passing data between classes.

### **Routing Management with `go_router`**

[go\_router on pub.dev](https://pub.dev/packages/go_router)

* **Official Flutter routing library**—works well for both **mobile and web**.
* Provides a **clear and scalable** way to manage navigation.

### **State Management with `flutter_bloc`**

[flutter\_bloc on pub.dev](https://pub.dev/packages/flutter_bloc)

* One of the **most popular and efficient** state management libraries.
* If you're new to `bloc`, check out my guide:

{% content-ref url="../state-management/bloc" %}
[bloc](https://wong-coupon.gitbook.io/flutter/state-management/bloc)
{% endcontent-ref %}

### **Code Generation with `json_serializable` & `freezed`**

[json\_serializable on pub.dev](https://pub.dev/packages/json_serializable)\
[freezed on pub.dev](https://pub.dev/packages/freezed)

* Reduces repetitive boilerplate code.
* Automatically generates helpful functions like `copyWith`, `fromJson`, and `toJson` for **easier data handling**.

### **Code Quality Improvement with `lint`**

[lint on pub.dev](https://pub.dev/packages/lint)

* Enforces **Effective Dart** coding standards.
* Ensures **consistent and readable** code across teams.
* If you haven’t read **Effective Dart**, check it out here: [Effective Dart](https://dart.dev/effective-dart).

### **App Icon Setup with `flutter_launcher_icons`**

[flutter\_launcher\_icons on pub.dev](https://pub.dev/packages/flutter_launcher_icons)

* Automatically generates **app icons** for both **Android and iOS**.
* Saves time when setting up project branding.

## **Creating a Base Project with Mason**

Below is how I structure the **`lib/` directory** in my base project:

```
lib/  
│── main.dart           # Runs the app, supports dev, staging, production environments  
│── router/             # Manages routes using `go_router`  
│── helper/             # Contains utility functions (e.g., localization, utilities)  
│── features/           # Stores the app’s main features, clearly separated  
│── config/             # Holds environment settings, API configurations, etc.  
```

Outside of the **`lib/`** folder, I also set up:

```
assets/                 # Stores images and localization files  
HELP.md                 # Project setup guide  
CHANGELOG.md            # Records version changes  
analysis_options.yaml   # Linting rules  
pubspec.yaml            # Dependency management  
build.yaml              # Build configuration  
```

You can check out my **base project template**, which is built using **Mason**, here:\
[dr\_base\_project on BrickHub](https://brickhub.dev/bricks/dr_base_project)

## **Setting Up the Development Environment**

A well-configured **development environment** helps prevent issues before the app reaches users.\
To **easily switch between environments** (dev, staging, production) **without manual changes**, I use an `enum` to store environment settings.

### **Defining the Environment Enum**

```dart
late EnviEnum ourEnvi;

enum EnviEnum {
  develop(
    code: 0,
    title: "develop",
    config: _BaseUrlConfig(baseUrl: "http://192.168.20.82:5173/"),
  ),
  staging(
    code: 1,
    title: "staging",
    config: _BaseUrlConfig(baseUrl: "https://staging-partner.kdmp.net/"),
  ),
  product(
    code: 2,
    title: "product",
    config: _BaseUrlConfig(baseUrl: "https://partners.kdmp.net/"),
  );

  const EnviEnum({required this.code, required this.title, required this.config});
  final int code;
  final String title;
  final _BaseUrlConfig config;

  String get baseUrl => config.baseUrl;
}

class _BaseUrlConfig {
  final String baseUrl;
  const _BaseUrlConfig({required this.baseUrl});
}
```

You can extend this enum to include additional configurations like **API keys**, **logging settings**, and more.

If you want a full setup for Android and iOS flavors (dev, staging, production), check this guide.\
I use `EnviEnum` to control environment logic in Dart, and Flavor to control native app config and Firebase files.

{% content-ref url="flavor" %}
[flavor](https://wong-coupon.gitbook.io/flutter/architecture-code/flavor)
{% endcontent-ref %}

### **Initializing the App for Each Environment**

**Development Environment (Local Server)**

```dart
void main() {
  ourEnvi = EnviEnum.develop;
  myMain(() {
    setup();
    runApp(const App());
  });
}
```

**Staging Environment (Internal Testing Before Release)**

```dart
void main() {
  ourEnvi = EnviEnum.staging;
  myMain(() {
    setup();
    runApp(const App());
  });
}
```

**Production Environment (Final Release for Users)**

```dart
void main() {
  ourEnvi = EnviEnum.product;
  myMain(() {
    setup();
    runApp(const App());
  });
}
```

## **Conclusion**

Setting up a **base project** in Flutter saves a lot of time when starting a new project, making it easier to maintain and scale.

* **Use Mason** to automatically generate necessary files and directories.
* **Leverage popular libraries** such as `go_router`, `flutter_bloc`, `json_serializable`, and `freezed` to enhance development efficiency.
* **Configure dev, staging, and production environments** to better manage application environments.

[Buy Me a Coffee](https://buymeacoffee.com/ducmng12g) | [Support Me on Ko-fi](https://ko-fi.com/I2I81AEJG8)
