Install and Create¶
Introduction¶
Getting started with Bond is designed to be as smooth as possible. In this guide, you'll install the Bond CLI, create your first project, and have a running Flutter app with all of Bond's features configured and ready to use.
By the end of this tutorial, you'll have:
- A complete Flutter app with production-ready structure
- Multiple build flavors (production and staging) configured
- Firebase integration set up
- All Bond packages integrated and working
- A clear understanding of how to add new features
Prerequisites¶
Before starting, ensure you have:
- Flutter SDK (3.10.0 or later) installed and configured
- Dart SDK (3.0.0 or later) - included with Flutter
- Git for version control
- VS Code or Android Studio for development
- Firebase CLI (we'll install this together)
You can verify your Flutter installation by running:
Make sure all checkmarks are green before proceeding.
Installing Bond CLI¶
The Bond CLI is your primary tool for creating projects, generating features, and managing Bond applications.
Install via Dart Pub¶
Verify Installation¶
You should see output similar to:
Update Your PATH¶
If the bond command isn't found, you may need to add Dart's global packages to your PATH:
macOS/Linux:
Windows:
Add %USERPROFILE%\AppData\Local\Pub\Cache\bin to your system PATH.
Creating Your First Project¶
The Bond CLI provides an interactive project creation experience that guides you through all the necessary configuration.
Start Project Creation¶
This will start an interactive wizard:
๐ Welcome to Bond CLI!
Let's create your new Flutter Bond project.
โ Enter Project Name: ยท my_awesome_app
โ Enter Project Description: ยท A new Flutter app built with Bond
โ Enter Organization (com.example): ยท com.mycompany
โ Enter iOS Bundle ID: ยท com.mycompany.myawesomeapp
โ Enter Android Application ID: ยท com.mycompany.myawesomeapp
โ Enable Analytics? (Y/n) ยท Yes
โ Enable Push Notifications? (Y/n) ยท Yes
โ Enable Social Authentication? (Y/n) ยท Yes
โ Choose Social Providers: ยท Google, Apple
๐ฏ Creating project structure...
๐ฆ Installing dependencies...
๐ฅ Configuring Firebase...
โ
Project created successfully!
Next steps:
1. cd my_awesome_app
2. Configure your environment files
3. Set up Firebase projects
4. Run flutter run --flavor staging
What Gets Created¶
The CLI generates a complete project structure:
my_awesome_app/
โโโ android/ # Android-specific configuration
โโโ ios/ # iOS-specific configuration
โโโ lib/
โ โโโ app/
โ โ โโโ app.dart # Main app configuration
โ โ โโโ app_run_tasks.dart
โ โโโ config/ # Environment configuration
โ โ โโโ analytics.dart
โ โ โโโ api.dart
โ โ โโโ cache.dart
โ โโโ core/ # Core utilities and providers
โ โโโ features/ # Feature modules
โ โ โโโ auth/
โ โ โโโ main/
โ โ โโโ notification/
โ โโโ providers/ # Service providers
โ โโโ main_production.dart
โ โโโ main_staging.dart
โโโ env.example.json # Environment template
โโโ pubspec.yaml
โโโ README.md
Project Structure Deep Dive¶
Let's explore the key parts of your new Bond project:
App Entry Points¶
Bond projects have separate entry points for each flavor:
lib/main_production.dart:
import 'package:flutter/material.dart';
import 'app/app.dart';
void main() => run(
() => const ProviderScope(child: BondApp()),
RunAppTasks(providers),
);
lib/main_staging.dart:
import 'package:flutter/material.dart';
import 'app/app.dart';
void main() => run(
() => const ProviderScope(child: BondApp()),
RunAppTasks(providers),
);
Service Providers¶
The heart of Bond's architecture is in lib/providers/:
lib/providers/app_service_provider.dart:
class AppServiceProvider extends ServiceProvider {
@override
Future<void> register(GetIt it) async {
// Register core app services
it.registerLazySingleton(() => NavigationService());
it.registerLazySingleton(() => ThemeService());
}
}
Feature Structure¶
Each feature follows a consistent pattern:
features/auth/
โโโ auth_service_provider.dart
โโโ data/
โ โโโ models/
โ โ โโโ user.dart
โ โโโ repositories/
โ โ โโโ auth_repository.dart
โ โโโ api/
โ โโโ auth_api_service.dart
โโโ presentation/
โโโ controllers/
โ โโโ login_form_controller.dart
โโโ pages/
โโโ login_page.dart
Configuration¶
Environment-specific configuration is handled through:
lib/config/api.dart:
class ApiConfig {
static String get baseUrl => env('API_BASE_URL');
static Duration get connectTimeout =>
Duration(seconds: env('CONNECT_TIMEOUT'));
}
Running Your Project¶
Set Up Environment¶
First, copy the environment template:
Edit env.json with your configuration:
{
"API_BASE_URL": "https://api.staging.myapp.com",
"CONNECT_TIMEOUT": "30",
"ANALYTICS_ENABLED": "true"
}
Run Staging Flavor¶
Run Production Flavor¶
You should see the Bond starter app running with: - A welcome screen - Navigation drawer with feature sections - Theme switching capability - Basic authentication flow
IDE Configuration¶
VS Code¶
Create .vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Staging",
"request": "launch",
"type": "dart",
"program": "lib/main_staging.dart",
"args": [
"--flavor", "staging",
"--dart-define-from-file=env.json"
]
},
{
"name": "Production",
"request": "launch",
"type": "dart",
"program": "lib/main_production.dart",
"args": [
"--flavor", "production",
"--dart-define-from-file=env.json"
]
}
]
}
Android Studio¶
- Go to Run โ Edit Configurations
- Click + โ Flutter
- Set Dart entrypoint to
lib/main_staging.dart - Set Additional arguments to
--flavor staging --dart-define-from-file=env.json - Repeat for production flavor
Adding Your First Feature¶
Let's add a simple "Posts" feature to understand Bond's workflow:
Generate Feature¶
This creates:
features/posts/
โโโ posts_service_provider.dart
โโโ data/
โ โโโ models/
โ โ โโโ post.dart
โ โโโ repositories/
โ โ โโโ posts_repository.dart
โ โโโ api/
โ โโโ posts_api_service.dart
โโโ presentation/
โโโ controllers/
โ โโโ posts_list_controller.dart
โโโ pages/
โโโ posts_page.dart
Register the Provider¶
Add to lib/app/app.dart:
final List<ServiceProvider> providers = [
// Existing providers...
PostsServiceProvider(), // Add this line
];
Implement the Model¶
features/posts/data/models/post.dart:
import 'package:json_annotation/json_annotation.dart';
part 'post.g.dart';
@JsonSerializable()
class Post {
final int id;
final String title;
final String body;
final int userId;
Post({
required this.id,
required this.title,
required this.body,
required this.userId,
});
factory Post.fromJson(Map<String, dynamic> json) => _$PostFromJson(json);
Map<String, dynamic> toJson() => _$PostToJson(this);
}
Generate JSON Serialization¶
Implement the API Service¶
features/posts/data/api/posts_api_service.dart:
class PostsApiService {
final BondFire _bondFire;
PostsApiService(this._bondFire);
Future<ListResponse<Post>> getPosts() {
return _bondFire
.get<ListResponse<Post>>('/posts')
.factory(ListResponse<Post>.fromJson)
.execute();
}
Future<Post> getPost(int id) {
return _bondFire
.get<Post>('/posts/$id')
.factory(Post.fromJson)
.execute();
}
}
Update Service Provider¶
features/posts/posts_service_provider.dart:
class PostsServiceProvider extends ServiceProvider with ResponseDecoding {
@override
Future<void> register(GetIt it) async {
it.registerLazySingleton(() => PostsApiService(it()));
it.registerLazySingleton(() => PostsRepository(it()));
it.registerFactory(() => PostsListController(it()));
}
@override
Map<Type, JsonFactory> get factories => {
Post: (json) => Post.fromJson(json),
};
}
Test Your Feature¶
Run the app and navigate to the Posts section. You should see your new feature integrated seamlessly with the rest of the app.
Understanding Bond's Architecture¶
Service Provider Pattern¶
Every feature in Bond is organized around a Service Provider that:
- Registers Dependencies: APIs, repositories, controllers
- Defines Model Factories: JSON conversion for networking and caching
- Maintains Boundaries: Each feature is self-contained
Dependency Injection¶
Bond uses GetIt for dependency injection:
// Register in Service Provider
it.registerLazySingleton(() => PostsRepository(it()));
// Use anywhere in the app
final postsRepo = GetIt.instance<PostsRepository>();
Feature Boundaries¶
Each feature should: - Have its own Service Provider - Define its own models and APIs - Not directly import from other features - Communicate through well-defined interfaces
Next Steps¶
Now that you have a working Bond project:
- Configure Environments: Set up your staging and production API endpoints
- Set Up Firebase: Configure authentication and analytics
- Explore Packages: Learn about BondFire, Forms, Cache, and Notifications
- Build Features: Add your app's unique functionality
- Deploy: Set up CI/CD for automated builds
Recommended Learning Path¶
- Environment Configuration - Set up your API endpoints and secrets
- Firebase Setup - Configure authentication and analytics
- Service Providers - Deep dive into Bond's architecture
- Data & Networking - Learn BondFire for API calls
- Forms - Build robust forms with validation
Troubleshooting¶
Common Issues¶
Bond CLI not found:
Flutter doctor issues:
Build errors after project creation:
Environment variables not working:
Getting Help¶
- Documentation: Check the specific guides for detailed information
- GitHub Issues: Report bugs or request features
- Discord Community: Get help from other Bond developers
- Stack Overflow: Tag questions with
flutter-bond
Conclusion¶
You now have a complete Bond application running with:
- โ Production-ready project structure
- โ Multiple build flavors configured
- โ Service Provider architecture in place
- โ Environment management set up
- โ Your first custom feature added
Bond provides the foundation - now you can focus on building your app's unique features without worrying about the underlying infrastructure.
The next step is to configure your environments and set up Firebase to unlock Bond's full potential.