PHPackages                             hussiensulyman/modulate - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. hussiensulyman/modulate

ActiveLibrary[Framework](/categories/framework)

hussiensulyman/modulate
=======================

A modular monolith architecture toolkit for Laravel.

v1.0.0(1mo ago)12MITPHPPHP ^8.2CI passing

Since May 1Pushed 1mo agoCompare

[ Source](https://github.com/hussiensulyman/modulate)[ Packagist](https://packagist.org/packages/hussiensulyman/modulate)[ RSS](/packages/hussiensulyman-modulate/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (5)Versions (8)Used By (0)

modulate
========

[](#modulate)

**The pragmatic middle ground between monolith spaghetti and microservices complexity.**

A Laravel package that scaffolds a clean modular monolith architecture — with enforced boundaries, self-contained modules, a built-in violation checker, and a natural extraction path to microservices when you actually need it.

[![License: MIT](https://camo.githubusercontent.com/08cef40a9105b6526ca22088bc514fbfdbc9aac1ddbf8d4e6c750e3a88a44dca/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d626c75652e737667)](LICENSE)[![Status: Stable](https://camo.githubusercontent.com/f3adeea933a64c2014c89092040b8c02f4931f3f5a5d46a189133d4ac21d0ebf/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7374617475732d737461626c652d627269676874677265656e)](https://packagist.org/packages/hussiensulyman/modulate)[![PHP: ^8.2](https://camo.githubusercontent.com/8b0c20237824d004f37b8c2adb4917d5f345147aa7b999000dceb4a5d64e541a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d253545382e322d373737424234)](https://php.net)[![Laravel: ^10|^11|^12](https://camo.githubusercontent.com/cbcfb0217a20bf9e777e5b68c36d3014064b4bb41af75c42e79ec6f61ce5677d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d2535453130253743253545313125374325354531322d464632443230)](https://laravel.com)[![Packagist Version](https://camo.githubusercontent.com/a80d72c0b8e4cdfb27786ba82aef0e4552822174fe96ba06d73c9999f034c5c3/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6875737369656e73756c796d616e2f6d6f64756c617465)](https://packagist.org/packages/hussiensulyman/modulate)[![Packagist Downloads](https://camo.githubusercontent.com/f67c80e7cc485325e3164814d3670c875c64e7b2c06afff0601b604b8f992db5/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6875737369656e73756c796d616e2f6d6f64756c617465)](https://packagist.org/packages/hussiensulyman/modulate)[![Tests](https://github.com/hussiensulyman/modulate/actions/workflows/tests.yml/badge.svg)](https://github.com/hussiensulyman/modulate/actions/workflows/tests.yml)

---

Why Modulate?
-------------

[](#why-modulate)

Every Laravel project eventually faces the same crossroads:

- **Stay monolithic** → controllers call models call models, no boundaries, refactoring becomes archaeology
- **Go microservices** → Kubernetes, Docker, service meshes, distributed tracing — for an app with 200 users

Modulate is the third option. Your app stays a single deployable unit, but internally it's divided into strict, self-contained modules that can be extracted into real microservices later — without rewriting everything.

```
app/
└── Modules/
    ├── Shared/          ← base classes, DTOs, exceptions, enums
    ├── Auth/            ← owns User model, authentication
    ├── Course/
    ├── Billing/
    └── Notification/

```

Each module owns its routes, models, migrations, services, events, and tests. Modules talk to each other only through published contracts and events. When a module needs to become its own service, you move the folder and swap the bindings. That's it.

---

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 10 or 11

---

Installation
------------

[](#installation)

```
composer require hussiensulyman/modulate:^1.0
```

### New project

[](#new-project)

Run `modulate:init` immediately after creating a fresh Laravel project. It cleans up the default boilerplate and sets up the modular structure:

```
php artisan modulate:init
```

This will:

- Generate a `Shared/` module with base classes (DTOs, Exceptions, Traits, Enums, Http, Support)
- Generate an `Auth/` module with `User` model already inside
- Move `app/Models/User.php` to `Auth` module + keep a compatibility alias in `app/Models/`
- Update `config/auth.php` to reflect the new `User` location (with `--strict`)
- Replace root `routes/web.php` and `routes/api.php` with thin comment stubs
- Delete the now-empty `app/Http/Controllers/` folder
- Keep `app/Http/Middleware/` with a README explaining it is for global middleware only
- Add `.gitkeep` + README in any emptied folders

**Options:**

```
php artisan modulate:init --strict        # move User with no alias (clean, no backward compat)
php artisan modulate:init --skip=shared   # skip generating the Shared/ module
php artisan modulate:init --dry-run       # preview all changes without applying them
```

### Existing project

[](#existing-project)

See [docs/migration-guide.md](docs/migration-guide.md) for a step-by-step incremental adoption guide.

---

Quickstart
----------

[](#quickstart)

### Create a module

[](#create-a-module)

```
php artisan modulate:make Course
```

Generated structure:

```
app/Modules/Course/
├── Contracts/
│   └── CourseServiceInterface.php
├── Controllers/
│   ├── Web/
│   └── Api/
├── Models/
├── Migrations/
├── Requests/
├── Resources/
├── Services/
│   └── CourseService.php
├── Events/
├── Listeners/
├── Routes/
│   ├── web.php
│   └── api.php
├── Tests/
│   ├── Unit/
│   ├── Feature/
│   └── E2E/
└── CourseServiceProvider.php

```

Plus a root-level `tests/E2E/` folder for cross-module journey tests (generated once on first `modulate:make`).

---

Flags
-----

[](#flags)

### Preset flags

[](#preset-flags)

```
php artisan modulate:make Course --minimal    # bare bones, single routes.php, no Events/Listeners/Resources
php artisan modulate:make Course --api-only   # no web routes or Web/ controllers
```

### Granular control

[](#granular-control)

```
# Add optional folders
php artisan modulate:make Course --add=repositories,actions,dtos,enums,policies

# Remove specific defaults
php artisan modulate:make Course --skip=events,listeners,e2e

# Add Dusk E2E stubs alongside default HTTP E2E stubs
php artisan modulate:make Course --add=dusk

# Combine freely
php artisan modulate:make Course --api-only --add=actions,dtos --skip=resources
```

### `--add` available values

[](#--add-available-values)

ValueGenerates`repositories``Repositories/` + `CourseRepositoryInterface.php` in `Contracts/``actions``Actions/` — single-responsibility action classes`dtos``DTOs/` — immutable `readonly` DTO classes`enums``Enums/``policies``Policies/` + `CoursePolicy.php``dusk`Dusk browser test stubs alongside HTTP E2E tests### `--skip` available values

[](#--skip-available-values)

`events`, `listeners`, `resources`, `requests`, `migrations`, `tests`, `e2e`

---

All Commands
------------

[](#all-commands)

### Setup

[](#setup)

```
php artisan modulate:install        # publish config and stubs
php artisan modulate:publish-stubs  # re-publish stubs only (after package upgrade)
php artisan modulate:init           # clean up Laravel boilerplate for a fresh project
```

### Scaffolding

[](#scaffolding)

```
php artisan modulate:make {Name}
php artisan modulate:make-service {Module} {Name}
php artisan modulate:make-event {Module} {Name}
php artisan modulate:make-contract {Module} {Name}
php artisan modulate:make-migration {Module} {Name}
```

### Module management

[](#module-management)

```
php artisan modulate:list
php artisan modulate:rename {OldName} {NewName} [--dry-run]
php artisan modulate:delete {Name} [--dry-run]
php artisan modulate:move {Name} {NewPath} [--dry-run]
```

### Health &amp; integrity

[](#health--integrity)

```
php artisan modulate:health    # verify all modules load without errors
php artisan modulate:check     # detect coupling violations
php artisan modulate:lint      # alias for modulate:check (CI-friendly)
php artisan modulate:graph     # visualize module dependency graph
```

### CI with GitHub Actions

[](#ci-with-github-actions)

```
name: Modulate Lint

on:
    pull_request:
    push:
        branches: [main, master]

jobs:
    modulate-lint:
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v4

            - uses: shivammathur/setup-php@v2
                with:
                    php-version: '8.3'
                    tools: composer:v2

            - name: Install dependencies
                run: composer install --prefer-dist --no-progress --no-interaction

            - name: Run Modulate lint
                uses: hussiensulyman/modulate/.github/actions/modulate-lint@v1.0.0
                with:
                    working-directory: ./
                    config-path: config/modulate.php
                    fail-on-violations: 'true'
```

The reusable action works the same whether `hussiensulyman/modulate` is installed from Packagist or via a Composer path repository, as long as dependencies are installed before running the action.

### Microservices

[](#microservices)

```
php artisan modulate:extract {Name}   # generate tailored extraction checklist
```

Use `php artisan modulate:doctor` to scan installed packages against known compatibility notes.

---

The Three Rules
---------------

[](#the-three-rules)

### 1. Modules never touch each other's internals

[](#1-modules-never-touch-each-others-internals)

```
// ❌ Never — direct cross-module model access
$course = \App\Modules\Course\Models\Course::find($id);

// ✅ Always — through a published contract
$course = app(CourseRepositoryInterface::class)->find($id);
```

### 2. Queries use contracts. Side effects use events.

[](#2-queries-use-contracts-side-effects-use-events)

```
// Need data from another module → contract
$user = app(UserServiceInterface::class)->find($userId);

// Something happened → event
event(new SubscriptionActivated($userId, $planId));
```

### 3. Each module is self-contained

[](#3-each-module-is-self-contained)

A module registers its own routes, migrations, and bindings through its `ServiceProvider`. No central wiring required.

---

The Shared Module
-----------------

[](#the-shared-module)

`modulate:init` generates a `Shared/` module that provides base infrastructure for all other modules:

```
app/Modules/Shared/
├── DTOs/           ← abstract BaseDTO, other modules extend this
├── Exceptions/     ← AppException, ValidationException, NotFoundException
├── Traits/         ← shared traits across modules
├── Enums/          ← global enums: Status, Locale, Environment
├── Http/
│   ├── BaseController.php
│   ├── BaseRequest.php
│   └── BaseResource.php
└── Support/        ← helper classes, value objects

```

**Rule:** Shared contains no business logic, no routes, and no module-specific code — only infrastructure primitives.

---

Coupling Violation Detection
----------------------------

[](#coupling-violation-detection)

```
php artisan modulate:check
```

Detects:

- Direct Model imports across module boundaries
- Direct Service class imports not going through a contract
- Cross-module DB queries hitting another module's tables
- Missing contract bindings in a module's ServiceProvider
- Facade usage bypassing contracts (e.g. `Auth::user()` in a non-Auth module)
- Direct access to another module's config keys

Runs automatically on `php artisan optimize` when enabled. Detection combines fast regex rules and AST analysis via `nikic/php-parser`.

---

Third-Party Package Compatibility
---------------------------------

[](#third-party-package-compatibility)

Most Laravel packages work with Modulate without issues. The ones that generate code (Breeze, Jetstream, Filament) will place files in default Laravel locations — move them into the correct module afterward.

Packages that extend the `User` model (Sanctum, Spatie Permission, JWT) work fine as long as they reference the correct `User` class location. See [docs/compatibility.md](docs/compatibility.md) for a curated list of popular packages and their setup notes.

`modulate:doctor` is available and can be used in CI or locally to flag compatibility risks before deployment.

---

Versioning
----------

[](#versioning)

Modulate follows [Semantic Versioning](https://semver.org). Breaking changes are always a major version bump and always come with an upgrade guide in [UPGRADING.md](UPGRADING.md).

---

Further Reading
---------------

[](#further-reading)

- [docs/architecture.md](docs/architecture.md) — philosophy, Ports &amp; Adapters, bounded contexts
- [docs/commands.md](docs/commands.md) — full command reference
- [docs/migration-guide.md](docs/migration-guide.md) — adopting Modulate in an existing project
- [docs/microservices-extraction.md](docs/microservices-extraction.md) — extracting a module into a standalone service
- [docs/compatibility.md](docs/compatibility.md) — third-party package compatibility notes
- [docs/github-action.md](docs/github-action.md) — reusable `modulate:lint` GitHub Action and manual CI validation
- [UPGRADING.md](UPGRADING.md) — upgrade guides between major versions

---

Contributing
------------

[](#contributing)

See [CONTRIBUTING.md](CONTRIBUTING.md). Package compatibility entries in `docs/compatibility.md` are especially welcome as community contributions.

---

License
-------

[](#license)

Modulate is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance92

Actively maintained with recent releases

Popularity4

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

7

Last Release

39d ago

Major Versions

v0.3.1 → v1.0.02026-05-02

### Community

Maintainers

![](https://www.gravatar.com/avatar/aa97875e0a093885a69d018b8b3240229d74cb191df92113c8f30e572514d507?d=identicon)[hussiensulyman](/maintainers/hussiensulyman)

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/hussiensulyman-modulate/health.svg)

```
[![Health](https://phpackages.com/badges/hussiensulyman-modulate/health.svg)](https://phpackages.com/packages/hussiensulyman-modulate)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3325.1M337](/packages/psalm-plugin-laravel)[laravel/dusk

Laravel Dusk provides simple end-to-end testing and browser automation.

1.9k38.6M289](/packages/laravel-dusk)[laravel/pennant

A simple, lightweight library for managing feature flags.

58213.1M81](/packages/laravel-pennant)[typo3/cms

TYPO3 CMS is a free open source Content Management Framework initially created by Kasper Skaarhoj and licensed under GNU/GPL.

1.2k1.9M122](/packages/typo3-cms)[prestashop/prestashop

PrestaShop is an Open Source e-commerce platform, committed to providing the best shopping cart experience for both merchants and customers.

9.1k16.8k](/packages/prestashop-prestashop)[tempest/framework

The PHP framework that gets out of your way.

2.2k31.1k11](/packages/tempest-framework)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
