Skip to content

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:

flutter doctor

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

dart pub global activate bond_cli

Verify Installation

bond --version

You should see output similar to:

Bond CLI version 1.2.0

Update Your PATH

If the bond command isn't found, you may need to add Dart's global packages to your PATH:

macOS/Linux:

echo 'export PATH="$PATH":"$HOME/.pub-cache/bin"' >> ~/.bashrc
source ~/.bashrc

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

bond create project

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:

cp env.example.json env.json

Edit env.json with your configuration:

{
  "API_BASE_URL": "https://api.staging.myapp.com",
  "CONNECT_TIMEOUT": "30",
  "ANALYTICS_ENABLED": "true"
}

Run Staging Flavor

flutter run --flavor staging -t lib/main_staging.dart --dart-define-from-file=env.json

Run Production Flavor

flutter run --flavor production -t lib/main_production.dart --dart-define-from-file=env.json

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

  1. Go to Run โ†’ Edit Configurations
  2. Click + โ†’ Flutter
  3. Set Dart entrypoint to lib/main_staging.dart
  4. Set Additional arguments to --flavor staging --dart-define-from-file=env.json
  5. Repeat for production flavor

Adding Your First Feature

Let's add a simple "Posts" feature to understand Bond's workflow:

Generate Feature

bond create feature posts

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

flutter packages pub run build_runner build

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:

  1. Registers Dependencies: APIs, repositories, controllers
  2. Defines Model Factories: JSON conversion for networking and caching
  3. 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:

  1. Configure Environments: Set up your staging and production API endpoints
  2. Set Up Firebase: Configure authentication and analytics
  3. Explore Packages: Learn about BondFire, Forms, Cache, and Notifications
  4. Build Features: Add your app's unique functionality
  5. Deploy: Set up CI/CD for automated builds
  1. Environment Configuration - Set up your API endpoints and secrets
  2. Firebase Setup - Configure authentication and analytics
  3. Service Providers - Deep dive into Bond's architecture
  4. Data & Networking - Learn BondFire for API calls
  5. Forms - Build robust forms with validation

Troubleshooting

Common Issues

Bond CLI not found:

# Ensure Dart's bin directory is in your PATH
echo $PATH | grep pub-cache

Flutter doctor issues:

# Run flutter doctor and fix any issues before proceeding
flutter doctor

Build errors after project creation:

# Clean and rebuild
flutter clean
flutter pub get
flutter packages pub run build_runner build

Environment variables not working:

# Ensure you're passing the env file correctly
flutter run --dart-define-from-file=env.json

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.