Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Module Installer Laravel Package

joshbrw/laravel-module-installer

Composer installer that places Laravel modules in a custom Modules directory instead of vendor, so module code stays editable and autoload-friendly. A lightweight drop-in for modular Laravel projects, commonly used alongside nwidart/laravel-modules.

Deep Wiki
Context7

Getting Started

joshbrw/laravel-module-installer is a Composer plugin that registers a custom installer for packages whose composer.json declares "type": "laravel-module". Instead of landing in vendor/, those packages are unpacked into your nwidart Modules/ directory — so composer require acme/blog gives you Modules/Blog with a real, editable module tree.

Step 1 — install the plugin in the project root. It must go in require, not require-dev (see Gotchas).

composer require joshbrw/laravel-module-installer

Step 2 — allow the plugin (Composer ≥ 2.2) and set your target directory in the root composer.json:

{
    "require": {
        "joshbrw/laravel-module-installer": "^1.0",
        "nwidart/laravel-modules": "^10.0"
    },
    "extra": {
        "module-dir": "Modules"
    },
    "config": {
        "allow-plugins": {
            "joshbrw/laravel-module-installer": true
        }
    }
}

extra.module-dir defaults to Modules; set it explicitly anyway so the intent is documented. It is resolved relative to the project root, so "Modules" → <project>/Modules. Keep it in sync with config/modules.php → 'paths.modules'.

Step 3 — first use case: pull in a module.

composer require acme/blog
# - Installing acme/blog (1.2.0): Downloading...
# - Installing acme/blog (1.2.0) into Modules/Blog
php artisan module:enable Blog

The folder name is derived from the package name (normally the segment after the slash, StudlyCased), so pick package names that map cleanly to your namespace — acme/blog → Modules/Blog → Modules\Blog\. Verify with ls Modules on your very first install rather than assuming.

Where to look first if it misbehaves:

composer show acme/blog            # confirm "type : laravel-module"
grep -A2 'acme/blog' vendor/composer/installed.json   # look for "install-path": "../Modules/Blog"
composer install -vvv | grep -i install

install-path in vendor/composer/installed.json is the ground truth for where Composer thinks the package went.

Implementation Patterns

Authoring a module package

For a module to be picked up by the installer, its own composer.json must look like:

{
    "name": "acme/blog",
    "type": "laravel-module",
    "require": {
        "nwidart/laravel-modules": "^10.0"
    },
    "autoload": {
        "psr-4": {
            "Modules\\Blog\\": ""
        }
    },
    "extra": {
        "laravel": {
            "providers": ["Modules\\Blog\\Providers\\BlogServiceProvider"]
        }
    }
}

The type is the single switch that activates the plugin. Keep autoload.psr-4 accurate — Composer still generates autoload rules from this file even though the code lives outside vendor/, and a bad mapping produces class-not-found errors that look like an installer bug. Ship a module.json alongside it so nwidart can read providers, aliases, and files.

Local / in-house modules (the pattern you'll actually use daily)

Don't develop modules as published packages. Use a path repository with symlinking:

{
    "repositories": [
        {
            "type": "path",
            "url": "../packages/blog",
            "options": { "symlink": true }
        }
    ]
}

Now composer require acme/blog:dev-main symlinks ../packages/blog into Modules/Blog. Edit in the source repo, changes appear instantly, and composer update can't clobber your work. This is the setup that makes the plugin genuinely useful for a team.

Private/remote modules

For VCS-hosted modules add a vcs repository (or point at a private Packagist/Satis). Tag releases properly — without tags you'll be requiring dev-main and fighting minimum-stability.

Post-install integration checklist

After every composer require/install, the module is on disk but the app doesn't know about it yet:

php artisan module:enable Blog
php artisan module:list
php artisan optimize:clear

If the module registers routes/views, confirm modules_statuses.json now contains "Blog": true and that it's committed if you want consistent environments.

Deployment

The plugin works fine in CI/CD as long as it's a production dependency:

composer install --no-dev --no-interaction --prefer-dist
php artisan module:migrate --force

Add Modules/ to .gitignore when modules are exclusively Composer-managed — but do commit composer.lock and modules_statuses.json. If any module is instead created via php artisan module:make and committed, exempt it explicitly (!Modules/Local/). Decide per-directory who owns the files; mixing ownership is the #1 source of "my changes vanished" incidents.

Gotchas and Tips

  • allow-plugins is mandatory on Composer 2.2+. Without it Composer prints a warning and silently skips the plugin — your module ends up in vendor/ and Modules/ stays empty. This is the most common failure by far.
  • Never put the installer in require-dev. On composer install --no-dev the plugin isn't activated, so modules install into vendor/ on production while working locally. Nightmare to diagnose.
  • --no-plugins disables it too. If someone added that flag to a deploy script, modules silently land in vendor/.
  • Install order matters. If you add the plugin and the module in the same composer require invocation, the plugin may not be active for that transaction. Two commands: plugin first, then modules.
  • type typos fail silently. "laravel-modules", "laravel_module", or a missing type all fall back to the default library installer. composer show <pkg> reveals the resolved type.
  • composer remove acme/blog deletes Modules/Blog outright, including any uploads, migrations you edited, or local commits living only there. Same for composer update — packages are re-extracted from dist and local edits are lost. Only edit modules you own via a path repo.
  • Requiring a module whose directory already exists (e.g. you generated Modules/Blog with module:make) will overwrite it after a confirmation prompt. Rename one or the other.
  • Keep extra.module-dir and config/modules.php aligned. A mismatch (Modules/ vs modules/) works on macOS and explodes on a case-sensitive Linux CI box.
  • Composer still owns the lockfile entry. The package is in composer.lock and installed.json even though it isn't in vendor/. Don't hand-copy modules around — you'll desync the lock.
  • Debugging path resolution: composer install -vvv shows the resolved install path; vendor/composer/installed.json shows "install-path" for every package. Between those two you can diagnose any placement issue.
  • The package is unmaintained (last release Jan 2021). It's a thin pair of classes over LibraryInstaller, and it still works with Composer 2.x, but pin ^1.0, run composer diagnose after Composer upgrades, and be prepared to fork — the extension point is literally "subclass the installer and register your own supports()" if you need per-package paths or an alias type.
  • Alternative if this gets in the way: oomphinc/composer-installers-extender + composer/installers gives you installer-paths mapping for arbitrary package types, at the cost of more config.
  • Nested laravel-module dependencies also land in Modules/. That's usually desirable, but audit transitive module installs — you can end up with a Modules/ directory you never explicitly asked for.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo