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

Theme Installer Laravel Package

orchestra/theme-installer

Composer installer for Orchestra Platform themes that automatically places theme packages in the correct themes directory, streamlining installation and discovery within Orchestra applications.

View on GitHub
Deep Wiki
Context7

Getting Started

This is not an application-level library — you will never call a class from it in a controller or Blade view. It is a Composer plugin, so "getting started" means getting your composer.json and CI to accept it, then watching theme packages land in themes/ instead of vendor/.

Prerequisites. You are on an Orchestra Platform application (or a fork). This package has meaning only in that context; there is nothing here for vanilla Laravel. Confirm the platform major you run is the one this plugin's release line targets — the v1.1.0 notes ship no compatibility matrix.

Steps.

  1. Install it alongside a theme package:
    composer require orchestra/theme-installer
    composer require acme/theme-bootstrap   # any package with "type": "orchestra-theme"
    
  2. If you're on Composer 2.2+, the install will be blocked until you whitelist it. Add to composer.json:
    "config": {
        "allow-plugins": {
            "orchestra/theme-installer": true
        }
    }
    
    Do this before you run composer install inside Docker or CI, or your first pipeline run becomes your discovery mechanism.
  3. Verify placement. After install, the theme should appear under themes/<name>/, not vendor/acme/theme-bootstrap/. Run composer install -vvv if you need to see which installer claimed the package.

Where to look first.

  • The theme package's own composer.json — its "type" field is the entire contract. If it isn't exactly orchestra-theme, nothing else here applies.
  • The plugin's installer class (typically implementing Composer\Installer\InstallerInterface). Two methods matter: supports() (where the orchestra-theme type check lives) and getInstallPath() (where the themes/ path is derived). Everything else — install, update, uninstall — funnels through those two decisions.

First use case. Swap a hand-copied theme folder for a versioned package: composer require acme/theme-bootstrap:^2.0, delete the old directory, commit the composer.lock diff. You've just made theme rollback a git revert instead of an SFTP job.

Implementation Patterns

Theme-as-package distribution. Each theme ships as its own repo/package with "type": "orchestra-theme" and a semver tag. Consumers only ever see composer require acme/theme-x:^1.2. This is the only pattern where the plugin earns its keep — the theme code lives in themes/ (discoverable, greppable, editable during development) while remaining version-pinned via the lockfile.

Pin the plugin explicitly. Do not float on ^1.0 for a package with zero dependents and a stale PHP floor. Use an exact or tilde constraint (~1.1.0) and review the composer.lock diff on every bump. Treat the lockfile diff as the review artifact, not the release notes.

Multi-brand / per-tenant theming (staged). Two viable shapes:

  • Single deploy, multiple themes present: install every theme package as a normal dependency; application config selects which themes/ subdirectory to load at runtime. The plugin just guarantees all of them are on disk.
  • Per-environment theme set: don't try to conditionally install via the plugin — it installs what Composer resolves. Instead, use separate lockfiles or a build matrix per brand, each requiring a different theme package set, and deploy the corresponding artifact.

This plugin installs files. Theme activation, switching, and per-tenant assignment are your domain logic, not its.

CI/CD integration. The plugin must be whitelisted in the environment running composer install --no-interaction. Practical checklist:

  • allow-plugins committed to composer.json (not set via CLI flag per-run, which drifts).
  • themes/ added to the deploy artifact manifest — if your build assumes "repo + vendor/ is the artifact," it isn't anymore.
  • .gitignore decision: exclude themes/ (treat as Composer-owned, like vendor/) or commit it (defeats the purpose). Pick one and document it.

Fork-and-own. Realistic for a zero-dependent package: copy the installer class into app/../packages/ or an internal Composer plugin you own. It's roughly 100–150 lines — supports(), getInstallPath(), install/update/uninstall. You gain a maintainer, a PHP version you actually run, and a CI matrix. You lose nothing, because there is no upstream community to stay current with.

Verification spike before adopting. On a throwaway branch: install the plugin + one theme, run composer update, run composer remove on the theme, and change the configured themes path. Confirm where files land and, critically, what composer remove leaves behind. Do this before the plugin reaches a shared environment.

Gotchas and Tips

The silent misconfiguration. A theme package with "type" misspelled or absent falls through to Composer's default installer and lands in vendor/ — with no error. The symptom appears much later as "theme not found." When a theme seems missing, check its "type" field before debugging the plugin.

allow-plugins is a governance decision, not a config tweak. Composer 2.2+ blocks plugins by default because plugins execute arbitrary code at install time. Someone needs to sign off on whitelisting this. Do that in parallel with the technical spike, not after — it's the longer pole.

Custom vendor-dir breaks naive path resolution. If getInstallPath() derives the themes directory relative to the project root vs. the vendor directory, a non-default vendor-dir (common in monorepos and some Docker setups) can send themes to the wrong place. Verify with your actual vendor-dir setting, not the default.

Uninstall cleanup is the weak spot. Confirm whether composer remove acme/theme-bootstrap deletes themes/theme-bootstrap/ or leaves an orphan directory. Orphans are worse than they sound: the app may keep loading stale theme files that no longer have a lockfile entry. Check this in the spike; if it leaves debris, add a post-remove script or a CI cleanup step.

PHP 7.1 floor, unvalidated on 8.x. v1.1.0 sets a 7.1 minimum and shows no evidence of a PHP 8.1–8.3 CI matrix. The dependency-hygiene change — removing illuminate/support — is potentially breaking for anyone who relied on it transitively, and shipped as a minor bump. Before upgrading from a pre-1.1 line, confirm nothing in your code depended on that package and that the plugin source no longer touches Illuminate\ classes or Laravel global helpers. Budget ~half a day; the audit is the go/no-go gate, not the release notes.

Debugging. composer install -vvv prints the installer class that claimed each package — the fastest way to distinguish "plugin not whitelisted," "plugin didn't match the type," and "plugin matched but resolved the wrong path." Composer's install-time errors surface here, not as application stack traces, so front-line triage should escalate to whoever owns the plugin rather than debugging theme code.

Extension points are minimal by design. There is no service provider, no config file, no events. Your leverage points are: the package "type" string, the allow-plugins entry, and (if forked) the two installer methods. Don't look for a hooks API that isn't there.

Don't reach for this on vanilla Laravel. Blade namespaces, view path registration, and a Vite/asset build step already solve theme delivery. composer/installers handles generic custom install paths for a wide range of package types and is far better maintained — prefer it unless the orchestra-theme type is a hard platform requirement.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager