Skip to main content

Composer – Managing Plugins and Themes

Learn how to manage WordPress Core, plugins, and themes using Composer dependency management in Seravo's hosting environment.

Composer is the standard dependency management tool for PHP. It allows you to define your project's libraries, WordPress Core, plugins, and themes in a single composer.json file.

Using Composer makes deployment pipelines (CI/CD) repeatable and keeps your Git repository clean, since third-party source code (such as plugins from WordPress.org) does not need to be committed directly to your repository.

Seravo's default project template uses Composer out of the box, and we recommend it for all professionally maintained WordPress sites.

How Composer Works with WordPress

In a WordPress project, Composer is configured via the composer.json file located in the project root (/data/wordpress/). The configuration typically relies on three key sections: repositories, require, and extra.

1. Repositories (Package Sources)

To allow Composer to discover official WordPress plugins and themes, you need to configure WPackagist as a package source. WPackagist mirrors the entire WordPress.org plugin and theme directory as Composer-compatible packages.

"repositories": [
{
"type": "composer",
"url": "https://wpackagist.org",
"only": [
"wpackagist-plugin/*",
"wpackagist-theme/*"
]
}
]

You can also add your own private Git repositories to this section later.

2. Required Packages (require)

This section lists all packages required by your site along with their version constraints. The example below installs WordPress Core, the mandatory Seravo plugin, and a plugin and theme from WPackagist:

"require": {
"php": ">=8.0",
"johnpbloch/wordpress-core": "^6.4",
"seravo/seravo-plugin": "*",
"wpackagist-plugin/two-factor": "^0.8",
"wpackagist-theme/twentytwentyfour": "*"
}
  • The caret constraint ^6.4 allows minor and patch updates (e.g., 6.4.1), while preventing automatic upgrades to the next major version (7.0).

  • The wildcard * installs the latest available version.

3. Installation Paths (extra.installer-paths)

By default, Composer installs all packages into the vendor/ directory in the project root. Because WordPress expects plugins and themes in specific directories, you must map the installation paths accordingly:

"extra": {
"installer-paths": {
"htdocs/wp-content/plugins/{$name}/": ["type:wordpress-plugin"],
"htdocs/wp-content/mu-plugins/{$name}/": ["type:wordpress-muplugin"],
"htdocs/wp-content/themes/{$name}/": ["type:wordpress-theme"]
},
"wordpress-install-dir": "htdocs/wordpress"
}

This configuration instructs composer/installers to automatically place any package of type wordpress-plugin into /htdocs/wp-content/plugins/.

Adding Custom Git Repositories (Themes and Plugins)

The best way to manage custom-built plugins and themes is to maintain them in their own dedicated Git repositories (e.g., on GitHub or Bitbucket) and pull them into your main project via Composer.

1. Create a composer.json in the root of your theme or plugin:

{
"name": "company/custom-theme",
"type": "wordpress-theme",
"license": "GPL-3.0-or-later",
"description": "Custom client theme"
}

2. Add the Git source to your main project's composer.json:

Add a new entry to the existing repositories array:

"repositories": [
{
"type": "vcs",
"url": "[email protected]:company/custom-theme.git"
}
]

3. Require the package:

"require": {
"company/custom-theme": "dev-main"
}

Note: Using dev-main or dev-master always fetches the latest commit from that branch. You can also specify semantic version tags (such as 1.0.0) if you tag releases in your theme or plugin repository.

Commercial and Private WordPress Plugins

WPackagist only mirrors free plugins hosted on WordPress.org. For commercial Pro plugins (such as ACF Pro or Gravity Forms), there are two common ways to manage them alongside Composer:

  1. Commit the plugin code to your project repository:

    The simplest approach is to install the plugin manually and exclude it from Composer. Download the ZIP archive, extract it into wp-content/plugins/commercial-plugin/, and track that folder in Git by adding an exception to your .gitignore file:

    !htdocs/wp-content/plugins/commercial-plugin/
  2. Use third-party package repositories (Premium Repositories):

    Many teams use services like Private Packagist, Satis, or official vendor Composer endpoints (for example, ACF Pro provides an official composer.json-compatible repository URL for license holders). Authentication keys are typically stored in an auth.json file or via environment variables (.env).

Running Composer Commands

You can install and update dependencies in your local development environment or on the server via SSH (from the project root /data/wordpress/):

  • composer install – Installs the exact package versions locked in composer.lock. (This is the command used by CI/CD pipelines and automated deployments).

  • composer update – Checks for newer compatible package versions, installs them, and updates composer.lock.

  • composer require wpackagist-plugin/plugin-name – Searches for the specified plugin, adds it to composer.json, and installs it immediately.

Common Issues and Troubleshooting

  • PHP runs out of memory (Allowed memory size exhausted): Resolving complex dependency trees can exceed the default PHP memory limit. Bypass the limit for a single run using COMPOSER_MEMORY_LIMIT=-1 composer update.

  • Private Git repository download fails (Permission denied): Connect to the server with SSH agent forwarding enabled (ssh -A user@server) so Composer can authenticate using your local SSH keys. Alternatively, store your API tokens in an auth.json file in the project root (ensure auth.json is ignored in .gitignore).

  • Package installs into vendor/ instead of wp-content/: Check that the package's own composer.json defines the proper package type ("type": "wordpress-plugin", "wordpress-theme", or "wordpress-muplugin").

  • Lock file mismatch (composer.lock is not up to date): If composer.json was edited manually, update the lock file's content hash by running composer update --lock.

See Also

If you need assistance configuring SSH keys for private Git repositories on Seravo's servers or troubleshooting Composer deployment pipelines, contact our support team at [email protected].

Did this answer your question?