Getting Mosaic Into Your Project
This guide will help you add Mosaic to your Flutter app step by step. Don’t worry - it’s simpler than it looks!
What You Need
Before starting, make sure you have:
- Flutter installed on your computer
- A Flutter project (new or existing)
- A code editor like VS Code
Step 1: Add Mosaic to Your Project
Open your pubspec.yaml
file (it’s in the root of your Flutter project) and add Mosaic:
dependencies:
flutter:
sdk: flutter
mosaic: ^0.1.2 # Add this line
Then run this command to download Mosaic:
flutter pub get
That’s it! Mosaic is now part of your project.
Step 2: Test That It Works
Let’s make sure everything is working. Create a simple test file to check:
// test/mosaic_test.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:mosaic/mosaic.dart';
void main() {
test('Mosaic is working', () {
// If this doesn't crash, Mosaic is installed correctly
expect(events, isNotNull);
expect(moduleManager, isNotNull);
});
}
Run the test:
flutter test test/mosaic_test.dart
If it passes, you’re ready to go!
Step 3: Organize Your Project
Mosaic works best when your project is organized. Here’s a simple folder structure:
lib/
├── main.dart # Your app's starting point
├── modules/ # All your modules go here
│ ├── home/ # Home module
│ ├── profile/ # Profile module
│ └── settings/ # Settings module
└── shared/ # Code shared between modules
├── constants/ # App-wide constants
└── utils/ # Helper functions
You don’t need to create all these folders right away - just make the modules
folder for now.
Step 4: Define Your App’s Modules
Think about what main sections your app has. For a simple app, you might have:
// lib/shared/module_enum.dart
enum ModuleEnum {
home, // Main screen users see first
profile, // User profile and account
settings; // App settings and preferences
// Helper method to convert strings to modules
static ModuleEnum? fromString(String name) {
for (ModuleEnum module in ModuleEnum.values) {
if (module.name == name) return module;
}
return null;
}
}
This enum lists all the major sections of your app. Start small - you can always add more later.
Step 5: Set Up Logging (Optional but Helpful)
Mosaic includes a logging system that helps you understand what’s happening in your app. Set it up early:
// In your main.dart, before runApp()
void main() async {
// Initialize logging
await logger.init(
tags: ['app', 'modules', 'events'], // Categories for your logs
dispatchers: [
ConsoleDispatcher(), // Shows logs in your development console
],
);
runApp(MyApp());
}
Now when things happen in your app, you can see what’s going on. This is especially helpful when learning how modules work.
Step 6: Create Your First Module
Let’s create a simple home module to make sure everything works:
// lib/modules/home/home_module.dart
import 'package:flutter/material.dart';
import 'package:mosaic/mosaic.dart';
class HomeModule extends Module {
// Every module needs a name
HomeModule() : super(name: 'home');
@override
Widget build(BuildContext context) {
// This is what users see when they're in this module
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Welcome to your modular app!',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// Send a message to other modules
events.emit<String>('home/button_pressed', 'Hello from Home!');
},
child: Text('Send Message'),
),
],
),
),
);
}
@override
Future<void> onInit() async {
// This runs once when the module is first set up
logger.info('Home module is starting up');
// Listen for messages from other modules
events.on<String>('app/welcome', (context) {
logger.info('Received welcome: ${context.data}');
});
}
@override
void onActive() {
// This runs every time the user switches to this module
logger.info('User is now viewing the home screen');
}
}
Step 7: Connect Everything in main.dart
Now update your main.dart to use modules:
// lib/main.dart
import 'package:flutter/material.dart';
import 'package:mosaic/mosaic.dart';
import 'modules/home/home_module.dart';
import 'shared/module_enum.dart';
void main() async {
// Set up logging first
await logger.init(
tags: ['app', 'modules', 'events'],
dispatchers: [ConsoleDispatcher()],
);
// Register your modules
moduleManager.modules['home'] = HomeModule();
moduleManager.defaultModule = 'home'; // Start with home module
// Initialize the router
router.init(ModuleEnum.home);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My Modular App',
theme: ThemeData(primarySwatch: Colors.blue),
home: ModularApp(), // This displays the current module
);
}
}
Step 8: Run Your App
Now run your app:
flutter run
You should see:
- A home screen with welcome text
- A button that sends messages
- Log messages in your console showing what’s happening
What Just Happened?
You’ve created your first modular app! Here’s what’s happening:
- Mosaic is managing modules - The
moduleManager
keeps track of all your modules - The router shows the right module -
ModularApp()
displays whichever module is currently active - Modules can communicate - When you press the button, it sends an event that other modules could listen to
- Everything is logged - You can see what’s happening in your development console
Next Steps
Now that you have the basics working:
- Add more modules - Create profile and settings modules
- Learn about navigation - How to switch between modules
- Try UI injection - Have one module add widgets to another
- Experiment with events - Make modules talk to each other
The next sections will show you how to do all of these things with simple, clear examples.
Troubleshooting
“Package mosaic not found”
- Check that you added it correctly to
pubspec.yaml
- Run
flutter pub get
again
“ModularApp() not showing anything”
- Make sure you registered your modules in
main.dart
- Check that
router.init()
was called with a valid module
“Events not working”
- Verify that the module sending events is different from the one receiving
- Check that event names match exactly (case-sensitive)
Still stuck?
- Check the console for error messages
- Make sure your module names in the enum match the names you used when registering modules