π§ͺ mayr_fake_api
No internet? No backend? No problem.
A lightweight fake API simulator for Flutter and Dart apps β perfect for local development, prototyping, and offline testing.
With mayr_fake_api, you can simulate real REST API calls using simple JSON files β no server required.
π Overview
mayr_fake_api
intercepts network requests (e.g. from Dio or http) and serves data from local JSON files in your Flutter appβs assets/
directory.
Itβs designed to make your development flow smoother, faster, and independent of backend delays.
π Features
- πΎ Use local JSON files to simulate REST endpoints.
- π§ Supports folder-structured routing (e.g.
/api/user/profile.json
). - β‘ Supports multiple HTTP methods (
GET
,POST
,PUT
,DELETE
, etc.) using method-specific JSON naming. - β Built-in 404 simulation with customizable resolver.
- πͺ Dynamic data support with wildcards and placeholders.
- π² 50+ built-in placeholders powered by Faker: UUIDs, user data, addresses, dates, random values, and more.
- π― Parameterized placeholders:
$randomInt(min,max)
,$choose(a,b,c)
,$image(width,height)
. - π§ Custom placeholders: Define your own dynamic value generators.
- π Request context: Access
$method
,$path
,$query
in your responses. - π§± Lightweight β no dependencies on backend servers.
- π§ Ideal for demos, offline-first apps, and rapid prototyping.
- βοΈ Enable or disable fake mode at runtime
- π§ Simulate network delays
π οΈ Installation
Add this to your pubspec.yaml
:
dependencies:
mayr_fake_api: ^1.0.0
Then import it:
import 'package:mayr_fake_api/mayr_fake_api.dart';
π§© Directory Structure
By default, your fake API data can live anywhere in your project, but the conventional layout is:
assets/
api/
user/
profile/
get.json
post.json
put.json
delete.json
error.json
Each JSON file corresponds to a simulated endpoint.
And the JSON structures should contain statusCode and data. Example
{
"statusCode": 201,
"data": {
// ... The data here
}
}
π‘ How It Works
-
When you make a GET request to
/api/user/profile
, the package looks forapi/user/profile/get.json
. -
When you make a POST request to
/api/user/profile
, it looks forapi/user/profile/post.json
. -
You can use any folder structure, e.g.:
api/user/profile/get.json api/user/profile/update/post.json
-
If the file doesnβt exist, it returns a 404 response by default β but you can override that with a custom not-found resolver.
π§± Example Usage
1. Simple setup
import 'package:dio/dio.dart';
import 'package:mayr_fake_api/mayr_fake_api.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final dio = Dio();
await MayrFakeApi.init(
basePath: 'assets/api',
attachTo: dio,
delay: Duration(milliseconds: 500),
enabled: kDebugMode,
// resolveNotFound: ...
//
);
runApp(MyApp());
}
2. Make a request
final response = await dio.get('https://example.com/api/user/profile');
This will attempt to load api/user/profile/get.json
.
π§© Handling 404 Responses
If a requested JSON file doesnβt exist, a 404 is returned automatically.
You can customize what happens using:
MayrFakeApi.resolveNotFound((path, method) {
return MayrFakeResponse(
statusCode: 404,
data: {'error': 'No fake endpoint found for $method $path'},
);
});
π¨ Simulating Errors
To simulate API errors, create an error.json
file in any directory.
The error file can contain:
{
"statusCode": 500,
"data": {
"code": 500,
"message": "Internal server error",
"details": "Something went wrong"
}
}
When the API detects this file, it throws a fake error response automatically.
If the statusCode
is missing or set to 200
, the error file is ignored
βοΈ Dynamic Data
Excellent β thatβs a smart and elegant convention π
Using a reserved folder (like -
) to signal dynamic data routes keeps things clean and file-based while still flexible.
Hereβs the rewritten Dynamic Data section for your mayr_fake_api
README, following your api/user/-/profile/get.json
pattern π
βοΈ Dynamic Data
Dynamic routes let you simulate responses that change depending on runtime input β for example, when you want user-specific data, random IDs, or timestamps β all while keeping your API file-based.
To define a dynamic endpoint, include a -
segment in your path.
For example:
api/
user/
-/
profile/
get.json
The -
folder acts as a dynamic wildcard that can represent any runtime value.
Example Usage
If you make a request like:
final response = await dio.get('https://example.com/api/user/123/profile');
The package will automatically match and resolve:
api/user/-/profile/get.json
instead of looking for a literal /user/123/
path.
Dynamic Placeholder Replacement
Inside your dynamic JSON files, you can reference wildcard values and use built-in placeholders for realistic mock data:
{
"statusCode": 200,
"data": {
"id": "$uuid",
"userId": "$1",
"name": "$userFullName",
"email": "$userEmail",
"createdAt": "$timestamp"
}
}
Built-in Placeholders
Request Context:
$method
- HTTP method (GET, POST, etc.)$path
- Full request path$query
- Query parameters
Unique Identifiers:
$uuid
- UUID v4 (e.g.,550e8400-e29b-41d4-a716-446655440000
)$ulid
- ULID - Lexicographically sortable (e.g.,01HQZXVZQM7K9Q0W0R0W0R0W0R
)$id
- Random numeric ID (0-999999)$shortId
- Short alphanumeric ID (8 characters)$hash
- 40-character hexadecimal hash
Date & Time:
$timestamp
- ISO 8601 timestamp (e.g.,2025-01-15T10:30:45.123Z
)$datetime
- Same as $timestamp$now
- Same as $timestamp$date
- Current date (YYYY-MM-DD)$time
- Current time (HH:MM:SS)
User Data (via Faker):
$userId
- Random UUID for user ID$userEmail
- Random email address$username
- Random username$userFirstName
- Random first name$userLastName
- Random last name$userFullName
- Random full name$userAvatar
- Avatar image URL$userPhone
- Random phone number$userToken
- Random 64-character token
Location Data (via Faker):
$country
- Country name$countryCode
- Country code$city
- City name$state
- State name$address
- Street address$timezone
- Timezone$ipAddress
- Random IP address
Business Data (via Faker):
$currency
- Currency code (e.g., USD)$jobTitle
- Job title$companyName
- Company name$productName
- Product name$sku
- Product SKU
Random Data (via Faker):
$randomSentence
- Random lorem ipsum sentence$randomWord
- Random word$randomBool
- Random boolean (true/false)
Design/Visual:
$hexColor
- Hex color code (e.g., #FF5733)$color
- Color name$image(width,height)
- Placeholder image URL (e.g.,$image(300,200)
)
Other:
$version
- Random semantic version (e.g., 1.2.3)$statusCode
- HTTP status code (default: 200)
Parameterized Placeholders:
$randomInt(min,max)
- Random integer in range (e.g.,$randomInt(1,100)
)$randomFloat(min,max)
- Random float in range (e.g.,$randomFloat(0,1)
)$choose(a,b,c)
- Randomly picks one option (e.g.,$choose(red,green,blue)
)
Wildcard Values:
$1
,$2
,$3
, etc. - Replaced with wildcard values from URL path
Custom Placeholders
You can also define custom placeholders:
await MayrFakeApi.init(
basePath: 'assets/api',
attachTo: dio,
customPlaceholders: {
'sessionId': () => 'session-${DateTime.now().millisecondsSinceEpoch}',
'apiVersion': () => 'v2.0',
'environment': () => kDebugMode ? 'dev' : 'prod',
},
);
Then in your JSON:
{
"statusCode": 200,
"data": {
"sessionId": "$sessionId",
"apiVersion": "$apiVersion",
"environment": "$environment"
}
}
Example Usage
{
"statusCode": 200,
"data": {
"user": {
"id": "$uuid",
"name": "$userFullName",
"email": "$userEmail",
"avatar": "$userAvatar",
"phone": "$userPhone",
"address": {
"street": "$address",
"city": "$city",
"state": "$state",
"country": "$country",
"zip": "$randomInt(10000,99999)"
}
},
"metadata": {
"timestamp": "$timestamp",
"version": "$version",
"statusCode": "$statusCode",
"requestId": "$shortId"
}
}
}
Example in Action
Given this structure:
api/
user/
-/
profile/
get.json
and get.json
containing:
{
"statusCode": 200,
"data": {
"userId": "$1",
"name": "User $1",
"timestamp": "$timestamp"
}
}
A request like:
final res = await api.request('/user/42/profile', method: 'GET');
print(res.data);
will output something like:
{
"statusCode": 200,
"data": {
"id": "42",
"name": "User #42",
"fetched_at": "2025-10-06T12:34:56.789Z"
}
}
Notes
- You can include multiple wildcards, e.g.
/api/user/-/posts/-/get.json
. Placeholders$1
,$2
,$3
, etc. will be replaced accordingly. - If no placeholder is found, the file is returned as-is.
- Works seamlessly with all HTTP methods (
GET
,POST
, etc.). - 50+ built-in placeholders available for realistic mock data (powered by Faker)
- Supports parameterized placeholders for dynamic ranges and choices
- Custom placeholders can be defined during initialization to generate dynamic values
- All placeholders are evaluated fresh on each request for realistic data
πͺΆ Empty JSON Files
If a JSON file exists but is empty, the API returns a 204 No Content response automatically.
π Example Directory Recap
api/
user/
profile/
get.json -> returns profile data
post.json -> simulate POST update
error.json -> simulate error
products/
get.json -> product listing
details/get.json -> single product details
π§ͺ Example Usage
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final dio = Dio(
// ... DIO setup here
);
await MayrFakeApi.init(
basePath: 'assets/api',
attachTo: dio,
delay: Duration(milliseconds: 500),
);
// rest of code
}
void elsewhere() async {
final response = await dio.get('api/user');
}
π’ Additional Information
π€ Contributing
Contributions are highly welcome! If you have ideas for new extensions, improvements, or fixes, feel free to fork the repository and submit a pull request.
Please make sure to:
- Follow the existing coding style.
- Write tests for new features.
- Update documentation if necessary.
Let's build something amazing together!
π Reporting Issues
If you encounter a bug, unexpected behaviour, or have feature requests:
- Open an issue on the repository.
- Provide a clear description and steps to reproduce (if it's a bug).
- Suggest improvements if you have any ideas.
Your feedback helps make the package better for everyone!
π§βπ» Author
MayR Labs
Crafting clean, reliable, and human-centric Flutter and Dart solutions. π mayrlabs.com
π Licence
This package is licensed under the MIT License β which means you are free to use it for commercial and non-commercial projects, with proper attribution.
See the LICENSE file for more details.
MIT Β© 2025 MayR Labs
π Support
If you find this package helpful, please consider giving it a βοΈ on GitHub β it motivates and helps the project grow!
You can also support by:
- Sharing the package with your friends, colleagues, and tech communities.
- Using it in your projects and giving feedback.
- Contributing new ideas, features, or improvements.
Every little bit of support counts! ππ
Libraries
- mayr_fake_api
- A Flutter package that intercepts API calls and returns fake JSON responses from local files during development.