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.
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
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!
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
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.
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.
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
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!
}
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:
Singleton
Factory
Lazy Singleton
// 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!' );
}
}