Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/khode-io/nest-dart/llms.txt

Use this file to discover all available pages before exploring further.

Quick start

This guide will walk you through creating your first Nest Dart application. You’ll learn how to set up modules, register services, and use dependency injection.
Make sure you have installed Nest Dart before starting this tutorial.

What you’ll build

You’ll create a simple application with:
  • A LoggerService for logging messages
  • A UserService that depends on the logger
  • Modules to organize and wire up the services
  • An application container to manage everything

Create your first service

1

Create a logger service

First, create a simple service for logging. This will be used by other services in your application.
class LoggerService {
  void log(String message) {
    print('[LOG] ${DateTime.now()}: $message');
  }
}
Services are just regular Dart classes. No special annotations or inheritance required!
2

Create a user service

Now create a UserService that uses the logger:
class UserService {
  final LoggerService _logger;
  final List<String> _users = [];

  UserService(this._logger);

  void addUser(String name) {
    _users.add(name);
    _logger.log('User added: $name');
  }

  List<String> getAllUsers() {
    _logger.log('Getting all users');
    return List.unmodifiable(_users);
  }
}
Notice how UserService depends on LoggerService through constructor injection.

Create your modules

1

Create a core module

Create a module that provides the LoggerService and exports it for other modules to use:
import 'package:nest_core/nest_core.dart';

class CoreModule extends Module {
  @override
  Future<void> providers(Locator locator) async {
    locator.registerSingleton<LoggerService>(LoggerService());
  }
  
  @override
  List<Type> get exports => [LoggerService];
}
The exports list makes LoggerService available to modules that import CoreModule. Services are private by default.
2

Create a user module

Create a module for user-related functionality that imports CoreModule:
class UserModule extends Module {
  @override
  List<Module> get imports => [CoreModule()];
  
  @override
  Future<void> providers(Locator locator) async {
    locator.registerSingleton<UserService>(
      UserService(locator.get<LoggerService>()),
    );
  }
  
  @override
  List<Type> get exports => [UserService];
}
The UserModule imports CoreModule to access the LoggerService, then uses it to create the UserService.
3

Create the app module

Finally, create the root application module that brings everything together:
class AppModule extends Module {
  @override
  List<Module> get imports => [CoreModule(), UserModule()];
  
  @override
  Future<void> providers(Locator locator) async {
    // App-level services go here
  }
}

Initialize and use your application

1

Create the application container

Initialize the application container and register your root module:
void main() async {
  final container = ApplicationContainer();
  await container.registerModule(AppModule());
  
  // Your application is now ready!
}
2

Use the services

Get services from the container and use them:
void main() async {
  final container = ApplicationContainer();
  await container.registerModule(AppModule());
  
  // Get the UserService
  final userService = container.get<UserService>();
  
  // Use the service
  userService.addUser('Alice');
  userService.addUser('Bob');
  
  final users = userService.getAllUsers();
  print('All users: $users');
}

Complete example

Here’s the complete working example:
import 'package:nest_core/nest_core.dart';

// Services
class LoggerService {
  void log(String message) {
    print('[LOG] ${DateTime.now()}: $message');
  }
}

class UserService {
  final LoggerService _logger;
  final List<String> _users = [];

  UserService(this._logger);

  void addUser(String name) {
    _users.add(name);
    _logger.log('User added: $name');
  }

  List<String> getAllUsers() {
    _logger.log('Getting all users');
    return List.unmodifiable(_users);
  }
}

// Modules
class CoreModule extends Module {
  @override
  Future<void> providers(Locator locator) async {
    locator.registerSingleton<LoggerService>(LoggerService());
  }
  
  @override
  List<Type> get exports => [LoggerService];
}

class UserModule extends Module {
  @override
  List<Module> get imports => [CoreModule()];
  
  @override
  Future<void> providers(Locator locator) async {
    locator.registerSingleton<UserService>(
      UserService(locator.get<LoggerService>()),
    );
  }
  
  @override
  List<Type> get exports => [UserService];
}

class AppModule extends Module {
  @override
  List<Module> get imports => [CoreModule(), UserModule()];
  
  @override
  Future<void> providers(Locator locator) async {}
}

// Application
void main() async {
  final container = ApplicationContainer();
  await container.registerModule(AppModule());
  
  final userService = container.get<UserService>();
  
  userService.addUser('Alice');
  userService.addUser('Bob');
  
  final users = userService.getAllUsers();
  print('All users: $users');
}

Understanding the code

Services

Plain Dart classes with business logic. No special requirements.

Modules

Organize services and define dependencies between modules.

Providers

Register services in the dependency injection container.

Exports

Make services available to other modules that import this module.

Service registration types

You can register services in different ways:
// Created once and shared across the app
locator.registerSingleton<UserService>(UserService());
Use singletons for stateful services like data stores, factories for stateless utilities, and lazy singletons for expensive-to-create services.

Next steps

Congratulations! You’ve built your first Nest Dart application.

Core concepts

Deep dive into modules, providers, and dependency injection

Flutter guide

Learn how to use Nest Dart in Flutter applications

Dart Frog guide

Build backend APIs with Nest Dart and Dart Frog

Examples

Explore real-world example applications

Common patterns

Async service initialization

Some services require async initialization:
class DatabaseModule extends Module {
  @override
  Future<void> providers(Locator locator) async {
    // Async initialization
    final prefs = await SharedPreferences.getInstance();
    locator.registerSingleton<SharedPreferences>(prefs);
    
    // Use the async-initialized service
    locator.registerSingleton<ConfigService>(
      ConfigService(locator.get<SharedPreferences>()),
    );
  }
  
  @override
  List<Type> get exports => [SharedPreferences, ConfigService];
}

Lifecycle hooks

Modules can have lifecycle hooks for initialization and cleanup:
class DatabaseModule extends Module {
  @override
  Future<void> onModuleInit(Locator locator, ModuleContext context) async {
    final db = locator.get<DatabaseService>();
    await db.connect();
  }
  
  @override
  Future<void> onModuleDestroy(Locator locator, ModuleContext context) async {
    final db = locator.get<DatabaseService>();
    await db.disconnect();
  }
}

Checking container readiness

Wait for the container to be fully initialized:
void main() async {
  final container = ApplicationContainer();
  await container.registerModule(AppModule());
  
  if (container.isReady) {
    print('Container is ready!');
  }
}

Build docs developers (and LLMs) love