Modern WordPress development has increasingly embraced Composer as a way to manage dependencies and improve workflow consistency. Whether you’re using a custom Composer setup or a framework like Bedrock, WP Engine supports deploying these projects—with a few adjustments.
This guide covers how to structure and deploy a Composer-based site to WP Engine using GitHub Actions, including Bedrock-specific notes.
Benefits of Using Composer for WordPress
Composer is a dependency management tool in PHP that offers several advantages for WordPress development:
- Dependency Management: Easily manage WordPress core, plugins, themes, and PHP packages.
- Version Control: Keep track of exact versions of all dependencies, ensuring consistency across environments.
- Automation: Automate updates and deployments, reducing manual errors.
- Cleaner Repositories: Avoid committing vendor files or plugin code, keeping your repository clean and focused on custom code.
By leveraging Composer, you can create a more maintainable and scalable WordPress project.
Managing Plugins and Themes with WPackagist
WPackagist mirrors the WordPress.org plugin and theme directories as Composer packages, allowing you to manage them as dependencies.
At WP Engine, we believe that ensuring the stability and reliability of critical developer infrastructure is essential to the WordPress ecosystem. That’s why we’re now the maintainer of WPackagist.
To use WPackagist:
1. Add WPackagist as a repository in your composer.json:
{
"repositories": [
{
"type": "composer",
"url": "https://wpackagist.org"
}
]
}
Code language: JSON / JSON with Comments (json)
2. Require plugins or themes using the wpackagist-plugin or wpackagist-theme prefixes:
{
"require": {
"wpackagist-plugin/advanced-custom-fields": "^6.0",
"wpackagist-theme/twentytwentysix": "*"
}
}
Code language: JSON / JSON with Comments (json)
3. Run composer install to install the specified plugins and themes.
This approach ensures that your plugins and themes are version-controlled and can be easily updated or rolled back as needed.
Project Structure Considerations
Typical Composer-based sites move the WordPress core files to a different directory, for example /web or /public and with that the wp-content directory housing the plugins and themes will move there too. However, this is a different structure expected by WP Engine as a managed hosting platform. Bedrock also organizes WordPress files differently than the traditional structure expected by WP Engine.
Bedrock Structure:
├── composer.json
├── composer.lock
├── config/
├── web/
│ ├── app/ # wp-content equivalent
│ ├── wp/ # WordPress core
│ ├── index.php
│ └── wp-config.php
└── .env
Code language: PHP (php)
WP Engine Expected Structure:
├── wp-content/
├── wp-includes/
├── wp-admin/
├── index.php
├── wp-config.php
...
To deploy a Composer or Bedrock-based site to WP Engine, you’ll need to restructure your project during the deployment process to match WP Engine’s expectations.
Deployment with GitHub Actions
Use WP Engine’s official GitHub Action to automate deployments. This approach syncs your wp-content/ directory and runs Composer during the build step.
Standard Composer Setup
For sites using Composer with a standard WordPress structure:
name: Deploy to WP Engine
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
tools: composer:v2
- name: Install Composer dependencies
run: composer install --no-dev --optimize-autoloader --prefer-dist
- name: Deploy to WP Engine
uses: wpengine/github-action-wpe-site-deploy@v3
with:
WPE_SSHG_KEY_PRIVATE: ${{ secrets.WPE_SSHG_KEY_PRIVATE }}
WPE_ENV: your-environment-name
SRC_PATH: wp-content/
REMOTE_PATH: wp-content/
FLAGS: -azvr --inplace --delete --exclude='uploads'
Code language: JavaScript (javascript)
Including Composer Dependencies (Optional)
If your plugins or themes require PHP packages from vendor/, you’ll need to include it in the deployment. Since only wp-content/ is synced to WP Engine, copy vendor into wp-content/ and add a mu-plugin to load the autoloader:
- name: Install Composer dependencies
run: composer install --no-dev --optimize-autoloader --prefer-dist
- name: Prepare vendor for deployment
run: |
mkdir -p wp-content/mu-plugins
# Create autoloader mu-plugin
cat > wp-content/mu-plugins/00-autoloader.php << 'EOF'
<?php
/**
* Plugin Name: Composer Autoloader
* Description: Loads the Composer autoloader.
*/
if (file_exists($autoloader = dirname(__DIR__) . '/vendor/autoload.php')) {
require_once $autoloader;
}
EOF
# Copy vendor into wp-content for deployment
cp -r vendor wp-content/
- name: Deploy to WP Engine
...
Code language: PHP (php)
Composer’s autoloader uses relative paths, so it works correctly from wp-content/vendor/.
Bedrock Setup
For Bedrock projects, you’ll need to restructure from web/app/ to wp-content/ during the build.
Bedrock normally loads the Composer autoloader via its wp-config.php. Since WP Engine manages wp-config.php, the workflow below creates a mu-plugin to load it instead. The 00- prefix ensures it loads before other mu-plugins.
name: Deploy Bedrock to WP Engine
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
tools: composer:v2
- name: Install Composer dependencies
run: composer install --no-dev --optimize-autoloader --prefer-dist
- name: Restructure for WP Engine
run: |
mkdir -p deploy/wp-content/mu-plugins
# Create autoloader mu-plugin (WP Engine manages wp-config.php, so we load it here)
cat > deploy/wp-content/mu-plugins/00-autoloader.php << 'EOF'
<?php
/**
* Plugin Name: Composer Autoloader
* Description: Loads the Composer autoloader for WP Engine deployments.
*/
if (file_exists($autoloader = dirname(__DIR__) . '/vendor/autoload.php')) {
require_once $autoloader;
}
EOF
# Move app (wp-content equivalent) contents
cp -r web/app/plugins deploy/wp-content/
cp -r web/app/themes deploy/wp-content/
cp -r web/app/mu-plugins/* deploy/wp-content/mu-plugins/ 2>/dev/null || true
cp -r web/app/languages deploy/wp-content/ 2>/dev/null || true
# Move vendor for Composer autoloading
cp -r vendor deploy/wp-content/
- name: Deploy to WP Engine
uses: wpengine/github-action-wpe-site-deploy@v3
with:
WPE_SSHG_KEY_PRIVATE: ${{ secrets.WPE_SSHG_KEY_PRIVATE }}
WPE_ENV: your-environment-name
SRC_PATH: deploy/wp-content/
REMOTE_PATH: wp-content/
FLAGS: -azvr --inplace --delete --exclude='uploads'
Code language: PHP (php)
Setup Requirements
- SSH Key: Add your WP Engine SSH private key as a repository secret named
WPE_SSHG_KEY_PRIVATE. Generate via WP Engine User Portal > SSH Keys.
- Environment Name: Replace
your-environment-namewith your WP Engine environment name.
- Branch Triggers: Adjust the
branchestrigger as needed (e.g.,mainfor production,stagingfor staging).
Important Notes
- WordPress core: WP Engine manages core files. Only deploy your
wp-content/or equivalent. - Uploads: Media uploads are not included in deployments. Use SFTP or WP Engine’s backup/restore tools.
- Vendor directory: Required for Bedrock to enable the mu-plugin directory loader and any Composer dependencies. Include the
00-autoloader.phpmu-plugin to load it. - Environment variables: Bedrock uses
.envfiles. Ensure environment-specific config is handled appropriately for WP Engine. - First deploy: After your first deployment, log in to WordPress and activate your theme. The deploy uses
--deletewhich removes the default theme, so you’ll need to activate the theme you deployed.
