ApiDog Flutter Demo is a sample Flutter app built using Clean Architecture principles to demonstrate how to consume a REST API using ApiDog in a modular, reusable, and scalable way.
⚙️ Built with
Provider,flutter_dotenv, and a layered architecture:core,domain,data, andpresentation.
- ✅ Fetch a single
Pet - ✅ Fetch a list of
Pets - ✅ Environment management via
.envfiles - ✅ Proper separation of concerns through Clean Architecture
- ✅ Centralized error handling using
FailureandExceptionclasses - ✅ Generic API response handling with
ApiResponse<T>
lib/
├── core/
│ └── error/ → Error and exception handling
├── data/
│ ├── datasources/ → API services (http requests)
│ └── repositories/ → Repository implementations
├── domain/
│ ├── entities/ → Models and generic API responses
│ ├── repositories/ → Abstract repository interfaces
│ └── usecases/ → Reusable business logic
├── presentation/
│ ├── providers/ → State management
│ └── screens/ → UI layer (main screen)
└── main.dart → App entry point and config
This project uses flutter_dotenv to manage multiple environments such as development, staging, and production.
your_project/
└── environment/
├── .env.dev
├── .env.local
└── .env.prod
Example .env.dev:
API_URL=https://dev.api.apidog.com
Example .env.prod:
API_URL=https://api.apidog.com
By default, main.dart loads the .env.local file:
await dotenv.load(fileName: 'environment/.env.local');
final apiUrl = dotenv.env['API_URL']!;💡 You can change which
.envfile to load based on the environment or flavor you want to run.
If you want to mock API responses using local static JSON files, such as:
assets/mock/pet_response.json→ for a single pet detailassets/mock/pet_list_response.json→ for the list of pets
you can toggle this behavior using a JSON_DATA variable in your .env files.
ℹ️ Behavior based on
JSON_DATAvalue
- When
JSON_DATA=true, the app will load data from local static JSON files instead of making real API calls.- When
JSON_DATA=false, the app will use the live API defined in theAPI_URLvariable.
In the pet_item.dart file, each PetItem can be configured with a standalone boolean flag:
- When
standalone = true, the Pet Detail page will fetch data directly from ApiDog using the pet ID. - When
standalone = false, the Pet Detail page will receive the fullPetobject via props, and no extra fetch is performed.
✅ This allows you to decide if the pet should be fetched or passed via widget prop.
# .env.local, .env.dev, or .env.prod
JSON_DATA=false
API_URL=http://127.0.0.1:3658/<apidog_path>
---
## 🧪 How to Run
### ✅ Start the app
1. Make sure your `.env` files are created inside the `environment/` folder
2. Make sure to have API_URL variable from apidog
3. Make sure to have JSON_DATA variable setted to false/true
4. Run the app:
```bash
flutter pub get
flutter run
or for vs_code like, launch.json
{
"version": "1.0.0",
"configurations": [
{
"name": "Local",
"request": "launch",
"type": "dart",
"program": "lib/main.dart",
"args": [
"--dart-define=ENV=local"
]
},
]
}You can easily extend this project by adding more models and endpoints:
- Create a new
Entityclass - Add a new
ServiceandRepositoryImpl - Inject a new
FetchApiData<T>use case into your Provider
| Home Screen | Detail |
|---|---|
![]() |
![]() |
http– for HTTP requestsprovider– for state managementflutter_dotenv– for environment variable handlingjson_annotation– for JSON annotationjson_serializable– for JSON serialization
Have an idea or a bug fix? Feel free to open a pull request! ❤️
MIT License © 2025 Gionata Stante / Open Reply

