Skip to main content

Introduction

When building large-scale applications with Filament, you may want to organize your code using Domain-Driven Design (DDD) principles, splitting your application into self-contained modules. This guide explains how to integrate Filament with modular architecture packages like InterNACHI/Modular.

The modular approach

In a modular architecture, each domain of your application is structured as a separate Composer package, typically located in an app-modules/ directory. Each module contains its own:
  • Models and business logic
  • Filament resources, pages, and widgets
  • Service provider
  • Routes, views, and configurations
  • Tests
This approach offers several benefits:
  • Clear separation of concerns between domains
  • Easier team collaboration (different teams can own different modules)
  • Better testability and maintainability
  • Ability to reuse modules across projects

Setting up InterNACHI/Modular

First, install the modular package:
Create a new module:
This scaffolds a module structure:

Configuring the moduleโ€™s composer.json

Each module should require filament/filament and define its service provider:

Creating a Filament plugin for your module

Each module should define its own Filament plugin that registers its resources, pages, and widgets:

Registering plugins conditionally for specific panels

When you have multiple panels (e.g., admin, app, portal), youโ€™ll often want certain modules to only register their plugins for specific panels. Use Panel::configureUsing() in your moduleโ€™s service provider to conditionally register plugins.

Basic conditional registration

To register a plugin for all panels except one:

Using a match statement for multiple panels

When you need to register a plugin for specific panels or configure it differently per panel, use a match statement that calls $panel->plugin() directly:
This approach lets you configure each plugin instance differently based on the panel, while panels not matched in the statement simply donโ€™t receive the plugin.

Module directory structure

A well-organized module with Filament integration might look like this:

Sharing resources between panels

Sometimes you may want a resource to appear in multiple panels with different configurations. You can achieve this by using resource discovery with panel-specific customizations:
Then register with different capabilities:
The Panel::configureUsing() approach is powerful because it allows modules to configure themselves without requiring changes to your panel provider files. When you add or remove a module, its Filament integration is automatically handled.

Registering Livewire components from modules

If your module contains custom Livewire components used by Filament (such as custom pages or widgets), you can register them in the pluginโ€™s boot() method: