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:

  1. Mosaic is managing modules - The moduleManager keeps track of all your modules
  2. The router shows the right module - ModularApp() displays whichever module is currently active
  3. Modules can communicate - When you press the button, it sends an event that other modules could listen to
  4. Everything is logged - You can see what’s happening in your development console

Next Steps

Now that you have the basics working:

  1. Add more modules - Create profile and settings modules
  2. Learn about navigation - How to switch between modules
  3. Try UI injection - Have one module add widgets to another
  4. 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